https://mooseframework.inl.gov
ParsedDownSelectionPositions.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "libmesh/parallel.h"
12 #include "libmesh/parallel_algebra.h"
13 #include "libmesh/vector_value.h"
14 
16 
19 {
22  // Might as well offer block restriction as an additional down-selection criterion
25 
26  params.addRequiredParam<std::vector<PositionsName>>(
27  "input_positions",
28  "Positions object(s) that will be down-selected by this object. The order of the "
29  "down-selected positions is kept the same");
30 
31  // Parsed expression parameters
32  params.addRequiredCustomTypeParam<std::string>(
33  "expression",
34  "FunctionExpression",
35  "Parsed function expression to compute the selection criterion. Note that x,y,z and t can be "
36  "used in the expression without being declared as functors.");
37  params.addParam<std::vector<MooseFunctorName>>(
38  "functor_names", {}, "Functors to use in the parsed expression");
39  params.addParam<std::vector<std::string>>(
40  "functor_symbols",
41  {},
42  "Symbolic name to use for each functor in 'functor_names' in the parsed expression. If not "
43  "provided, then the actual functor names will be used in the parsed expression.");
44 
45  // We need to preserve the order of the positions from the input_positions objects
46  params.set<bool>("auto_sort") = false;
47  // We already perform a custom synchronization, because the functors cannot be evaluated on every
48  // domain
49  params.set<bool>("auto_broadcast") = false;
50 
51  // Keep as up-to-date as possible given the generality of functors
52  params.set<ExecFlagEnum>("execute_on") = {EXEC_LINEAR, EXEC_TIMESTEP_BEGIN};
53 
54  params.addClassDescription("Examines input positions object(s) to find all positions matching a "
55  "user-specifed parsed expression criterion. The order of the "
56  "positions in the input is kept.");
57  return params;
58 }
59 
61  : Positions(parameters),
63  BlockRestrictable(this),
64  FunctionParserUtils(parameters),
65  _expression(getParam<std::string>("expression")),
66  _xyzt({"x", "y", "z", "t"}),
67  _functor_names(getParam<std::vector<MooseFunctorName>>("functor_names")),
68  _n_functors(_functor_names.size()),
69  _functor_symbols(getParam<std::vector<std::string>>("functor_symbols"))
70 {
71  if (getParam<ExecFlagEnum>("execute_on").contains(EXEC_NONE))
72  paramError("execute_on",
73  "NONE execution flag not supported. Most functors (functions, variables, spatial "
74  "user objects for example) are not initialized at construction.");
75 
76  // sanity checks
77  if (!_functor_symbols.empty() && (_functor_symbols.size() != _n_functors))
78  paramError("functor_symbols", "functor_symbols must be the same length as functor_names.");
79 
80  // Make sure functors are not x, y, z, or t
81  for (const auto & name : _functor_symbols)
82  if (std::find(_xyzt.begin(), _xyzt.end(), name) != _xyzt.end())
83  paramError("functor_symbols", "x, y, z, and t cannot be used in 'functor_symbols'.");
84  for (const auto & name : _functor_names)
85  if (std::find(_xyzt.begin(), _xyzt.end(), name) != _xyzt.end())
86  paramError("functor_names",
87  "x, y, z, and t cannot be used in 'functor_names'. Use functor_symbols to "
88  "disambiguate by using a different symbol in the expression.");
89 
90  // build variables argument
91  std::string variables;
92 
93  // adding functors to the expression
94  if (_functor_symbols.size())
95  for (const auto & symbol : _functor_symbols)
96  variables += (variables.empty() ? "" : ",") + symbol;
97  else
98  for (const auto & name : _functor_names)
99  variables += (variables.empty() ? "" : ",") + name;
100 
101  // xyz and t are likely useful here
102  for (auto & v : _xyzt)
103  variables += (variables.empty() ? "" : ",") + v;
104 
105  // Create parsed function
106  _func_F = std::make_shared<SymFunction>();
107  parsedFunctionSetup(_func_F, _expression, variables, {}, {}, comm());
108 
109  // reserve storage for parameter passing buffer
110  _func_params.resize(_n_functors + 4);
111 
112  // keep pointers to the functors
113  for (const auto & name : _functor_names)
114  _functors.push_back(&getFunctor<Real>(name));
115 }
116 
117 void
119 {
120  if (!_initialized)
121  {
122  // Retrieve the input positions
123  const auto & base_names = getParam<std::vector<PositionsName>>("input_positions");
124  for (const auto & base_name : base_names)
125  if (_fe_problem.hasUserObject(base_name))
126  _positions_ptrs.push_back(&_fe_problem.getPositionsObject(base_name));
127 
128  // Check execute-ons
129  for (const auto pos_ptr : _positions_ptrs)
130  if (!pos_ptr->getExecuteOnEnum().contains(_fe_problem.getCurrentExecuteOnFlag()))
131  mooseInfo("Positions '",
132  pos_ptr->name(),
133  "' is not executing on ",
135  ". This could mean this position is not updated when down-selecting.");
136  }
137 
138  clearPositions();
139  const bool initial = _fe_problem.getCurrentExecuteOnFlag() == EXEC_INITIAL;
140 
141  // Pre-allocate for performance
142  unsigned int n_points = 0;
143  for (const auto pos_ptr : _positions_ptrs)
144  n_points += pos_ptr->getNumPositions(initial);
145  _positions.reserve(n_points);
146  mooseAssert(comm().verify(n_points), "Input positions should be synchronized");
147 
148  // Rather than synchronize all ranks at every point, we will figure out whether to keep (2),
149  // discard (1) or error (0, due to no ranks having made the decision) for each position
150  std::vector<short> keep_positions(n_points, PositionSelection::Error);
151 
152  const auto state = determineState();
153  auto pl = _fe_problem.mesh().getMesh().sub_point_locator();
154  pl->enable_out_of_mesh_mode();
155 
156  // Loop over the positions, find them in the mesh to form the adequate functor arguments
157  // Note that every positions object is assumed replicated over every rank already
158  unsigned int i_pos, counter = 0;
159  for (const auto & pos_ptr : _positions_ptrs)
160  for (const auto & pos : pos_ptr->getPositions(initial))
161  {
162  counter++;
163  i_pos = counter - 1;
164  // Get all possible elements the position may be in
165  std::set<const Elem *> candidate_elements;
166  (*pl)(pos, candidate_elements);
167 
168  for (const auto elem : candidate_elements)
169  {
170  // Check block restriction
171  // Dont exclude a point we already chose to keep. This 'inclusivity' means that a position
172  // at a node can be included if at least one element it borders is in the block restriction
173  if (!hasBlocks(elem->subdomain_id()) && (keep_positions[i_pos] != PositionSelection::Keep))
174  {
175  keep_positions[i_pos] = PositionSelection::Discard;
176  continue;
177  }
178 
179  // We can't guarantee we have enough algebraic ghosting for variable functors. Might as well
180  // skip, another process will take care of it
181  if (elem->processor_id() != processor_id())
182  continue;
183 
184  // Form a functor argument
185  const Moose::ElemPointArg elem_arg = {elem, pos, false};
186 
187  // Fill arguments to the parsed expression
188  // Functors
189  for (const auto i : index_range(_functors))
190  _func_params[i] = (*_functors[i])(elem_arg, state);
191 
192  // Positions and time
193  for (const auto j : make_range(Moose::dim))
194  _func_params[_n_functors + j] = pos(j);
195  _func_params[_n_functors + 3] = _t;
196 
197  // Evaluate parsed expression
198  const auto value = evaluate(_func_F);
199 
200  // Keep points matching the criterion
201  if (value > 0)
202  keep_positions[i_pos] = PositionSelection::Keep;
203  // Dont exclude a point we already chose to keep. This 'inclusivity'
204  // means that a position at an interface between elements can get included if the functor
205  // evaluates greater than 0 for any of the elements used in forming ElemPointArgs
206  else if (keep_positions[i_pos] != PositionSelection::Keep)
207  keep_positions[i_pos] = PositionSelection::Discard;
208  }
209  }
210 
211  // Synchronize which positions to keep across all ranks
212  comm().max(keep_positions);
213  i_pos = 0;
214  for (const auto & pos_ptr : _positions_ptrs)
215  for (const auto & pos : pos_ptr->getPositions(initial))
216  {
217  if (keep_positions[i_pos] == PositionSelection::Keep)
218  _positions.push_back(pos);
219  else if (keep_positions[i_pos] == PositionSelection::Error)
220  mooseError(
221  "No process has made a decision on whether position '",
222  pos,
223  "' from Positions object '" + pos_ptr->name() +
224  "' should be discarded or kept during down-selection. This usually means this "
225  "position is outside the mesh!");
226  i_pos++;
227  }
228 
229  _initialized = true;
230 }
An interface for accessing Moose::Functors for systems that do not care about automatic differentiati...
std::string name(const ElemQuality q)
GenericReal< is_ad > evaluate(SymFunctionPtr &, const std::string &object_name="")
Evaluate FParser object and check EvalError.
A MultiMooseEnum object to hold "execute_on" flags.
Definition: ExecFlagEnum.h:21
static InputParameters validParams()
Definition: Positions.C:15
std::vector< const Positions * > _positions_ptrs
Vector of pointers to positions objects.
void mooseInfo(Args &&... args) const
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
void clearPositions()
Clear all positions vectors.
Definition: Positions.C:154
Moose::StateArg determineState() const
Create a functor state argument that corresponds to the implicit state of this object.
const ExecFlagType EXEC_NONE
Definition: Moose.C:27
Positions objects are under the hood Reporters.
Definition: Positions.h:20
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:153
const Parallel::Communicator & comm() const
registerMooseObject("MooseApp", ParsedDownSelectionPositions)
bool hasUserObject(const std::string &name) const
Check if there if a user object of given name.
A structure that is used to evaluate Moose functors at an arbitrary physical point contained within a...
const Positions & getPositionsObject(const std::string &name) const
Get the Positions object by its name.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
bool _initialized
Whether the positions object has been initialized. This must be set by derived objects.
Definition: Positions.h:116
static InputParameters validParams()
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3443
const ExecFlagType EXEC_TIMESTEP_BEGIN
Definition: Moose.C:35
ParsedDownSelectionPositions(const InputParameters &parameters)
std::vector< Point > & _positions
For now, only the 1D vector will be shared across all ranks.
Definition: Positions.h:92
std::vector< const Moose::Functor< Real > * > _functors
Vector of pointers to functors.
const unsigned int _n_functors
Number of functors.
const ExecFlagType EXEC_LINEAR
Definition: Moose.C:29
std::string stringify(const T &t)
conversion to string
Definition: Conversion.h:64
void max(const T &r, T &o, Request &req) const
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
Definition: UserObject.h:211
std::vector< GenericReal< is_ad > > _func_params
Array to stage the parameters passed to the functions when calling Eval.
An interface that restricts an object to subdomains via the &#39;blocks&#39; input parameter.
IntRange< T > make_range(T beg, T end)
virtual MooseMesh & mesh() override
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
void addRequiredCustomTypeParam(const std::string &name, const std::string &custom_type, const std::string &doc_string)
These methods add an option parameter and with a customer type to the InputParameters object...
void initialize() override
In charge of computing / loading the positions.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
static InputParameters validParams()
static InputParameters validParams()
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
bool hasBlocks(const SubdomainName &name) const
Test if the supplied block name is valid for this object.
processor_id_type processor_id() const
SymFunctionPtr _func_F
function parser object for the local value of the expression
Positions of the centroids of all elements meeting the parsed expression criterion.
auto index_range(const T &sizable)
const ExecFlagType EXEC_INITIAL
Definition: Moose.C:28