25 "variable",
"The auxiliary variable to store the transferred values in.");
27 "The variable to transfer from.");
29 params.
addParam<std::vector<PostprocessorName>>(
30 "from_postprocessors_to_be_preserved",
31 "The name of the Postprocessor in the from-app to evaluate an adjusting factor.");
33 params.
addParam<std::vector<PostprocessorName>>(
34 "to_postprocessors_to_be_preserved",
36 "The name of the Postprocessor in the to-app to evaluate an adjusting factor.");
37 params.
addParam<
bool>(
"allow_skipped_adjustment",
39 "If set to true, the transfer skips adjustment when from or to " 40 "postprocessor values are either zero or have different signs. If set to " 41 "false, an error is thrown when encountering these conditions.");
43 "to_postprocessors_to_be_preserved allow_skipped_adjustment",
44 "Conservative transfer");
51 _from_var_names(isParamValid(
"source_variable")
52 ? getParam<
std::vector<VariableName>>(
"source_variable")
53 :
std::vector<VariableName>()),
54 _to_var_names(getParam<
std::vector<AuxVariableName>>(
"variable")),
55 _preserve_transfer(isParamValid(
"from_postprocessors_to_be_preserved")),
56 _from_postprocessors_to_be_preserved(
58 ? getParam<
std::vector<PostprocessorName>>(
"from_postprocessors_to_be_preserved")
59 :
std::vector<PostprocessorName>{}),
60 _to_postprocessors_to_be_preserved(
61 getParam<std::vector<PostprocessorName>>(
"to_postprocessors_to_be_preserved")),
62 _use_nearestpoint_pps(
false),
63 _allow_skipped_adjustment(getParam<bool>(
"allow_skipped_adjustment"))
65 if (_directions.size() != 1)
66 paramError(
"direction",
"This transfer is only unidirectional");
68 if (_preserve_transfer)
74 if (_to_var_names.size() != 1)
75 paramError(
"variable",
76 " Support single variable only when the conservative capability is on ");
78 if (_current_direction == TO_MULTIAPP)
80 if (_from_postprocessors_to_be_preserved.size() != getToMultiApp()->numGlobalApps() &&
81 _from_postprocessors_to_be_preserved.size() != 1)
82 paramError(
"from_postprocessors_to_be_preserved",
83 "Number of from-postprocessors should equal to the number of subapps, or use " 84 "NearestPointIntegralVariablePostprocessor");
85 if (_to_postprocessors_to_be_preserved.size() != 1)
86 paramError(
"to_postprocessors_to_be_preserved",
87 "Number of to-postprocessors should equal to 1");
89 else if (_current_direction == FROM_MULTIAPP)
91 if (_from_postprocessors_to_be_preserved.size() != 1)
92 paramError(
"from_postprocessors_to_be_preserved",
93 "Number of from Postprocessors should equal to 1");
95 if (_to_postprocessors_to_be_preserved.size() != getFromMultiApp()->numGlobalApps() &&
96 _to_postprocessors_to_be_preserved.size() != 1)
97 paramError(
"to_postprocessors_to_be_preserved",
98 "_to_postprocessors_to_be_preserved",
99 "Number of to Postprocessors should equal to the number of subapps, or use " 100 "NearestPointIntegralVariablePostprocessor ");
105 if (_to_var_names.size() == 0)
106 paramError(
"variable",
"You need to specify at least one variable");
109 if (_to_var_names.size() == 1)
110 _to_var_name = _to_var_names[0];
112 if (_from_var_names.size() == 1)
113 _from_var_name = _from_var_names[0];
134 " You have to specify ",
136 " regular from-postprocessors, or use NearestPointIntegralVariablePostprocessor ");
152 " You have to specify ",
154 " regular to-postprocessors, or use NearestPointIntegralVariablePostprocessor ");
164 std::vector<PostprocessorName> pps_empty;
166 auto & parent_app_pps =
168 for (
auto & pp : parent_app_pps)
176 "execute_on='transfer' is required in the conservative transfer for " +
type +
" '",
178 "' computed in the parent application.\n" 179 "Please add execute_on='transfer' to this postprocessor in the input file.\n" 180 "For a custom postprocessor, make sure that execute_on options are not hardcoded.");
184 for (
unsigned int i = 0; i < multi_app->numGlobalApps(); i++)
187 if (!multi_app->hasLocalApp(i))
194 for (
auto & sub_pp : sub_pps)
202 "execute_on='transfer' is required in the conservative transfer for " +
type +
" '",
204 "' in child application '" + multi_app->name() +
206 "Please add execute_on='transfer' to this postprocessor in the input file.\n" 207 "For a custom postprocessor, make sure that execute_on options are not " 219 TIME_SECTION(
"MultiAppConservativeTransfer::execute()",
221 "Post transfer to preserve postprocessor values");
230 for (
unsigned int i = 0; i <
getToMultiApp()->numGlobalApps(); i++)
283 PostprocessorName & from_postprocessor,
285 PostprocessorName & to_postprocessor)
306 from_adjuster = from_adjuster_tmp;
322 auto sys_num = to_sys.number();
326 auto & to_solution = to_var.sys().solution();
328 bool is_nodal = to_sys.variable_type(var_num).family ==
LAGRANGE;
331 for (
const auto & node : to_mesh.local_node_ptr_range())
334 if (node->n_dofs(sys_num, var_num) < 1)
340 auto ii = pps.nearestPointIndex(*node);
344 scale = from_adjuster / pps.userObjectValue(i);
351 scale = pps.userObjectValue(i) / to_adjuster;
355 dof_id_type dof = node->dof_number(sys_num, var_num, 0);
356 to_solution.set(dof,
scale * to_solution(dof));
361 for (
auto & elem :
as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
364 if (elem->n_dofs(sys_num, var_num) < 1)
370 unsigned int ii = pps.nearestPointIndex(elem->vertex_average());
374 scale = from_adjuster / pps.userObjectValue(i);
381 scale = pps.userObjectValue(i) / to_adjuster;
384 dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
385 to_solution.set(dof,
scale * to_solution(dof));
399 PostprocessorName & from_postprocessor,
401 PostprocessorName & to_postprocessor)
422 from_adjuster = from_adjuster_tmp;
440 auto sys_num = to_sys.number();
443 auto & to_solution = to_var.sys().solution();
445 auto & moose_mesh = to_problem.
mesh();
446 bool is_nodal = to_sys.variable_type(var_num).family ==
LAGRANGE;
449 for (
const auto & node : to_mesh.local_node_ptr_range())
452 if (node->n_dofs(sys_num, var_num) < 1)
455 bool scale_current_node =
false;
459 auto & blockids = pps->blockIDs();
460 auto & node_to_elem_map = moose_mesh.nodeToElemMap();
461 auto neighbor_elements = node_to_elem_map.find(node->id());
462 for (
auto element : neighbor_elements->second)
464 auto & elem = to_mesh.elem_ref(element);
465 if (blockids.find(elem.subdomain_id()) != blockids.end())
467 scale_current_node =
true;
474 scale_current_node =
true;
477 if (scale_current_node)
479 dof_id_type dof = node->dof_number(sys_num, var_num, 0);
480 to_solution.set(dof, (from_adjuster / to_adjuster) * to_solution(dof));
486 for (
auto & elem :
as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
489 if (elem->n_dofs(sys_num, var_num) < 1)
492 bool scale_current_element =
false;
495 auto & blockids = pps->blockIDs();
496 if (blockids.find(elem->subdomain_id()) != blockids.end())
498 scale_current_element =
true;
503 scale_current_element =
true;
505 if (scale_current_element)
507 unsigned int n_comp = elem->n_comp(sys_num, var_num);
509 for (
unsigned int offset = 0; offset < n_comp; offset++)
511 dof_id_type dof = elem->dof_number(sys_num, var_num, offset);
512 to_solution.set(dof, (from_adjuster / to_adjuster) * to_solution(dof));
534 mooseError(
"Adjustment postprocessors from: ",
538 " must both have the same sign and be different from 0");
const ExecFlagType EXEC_TRANSFER
const std::shared_ptr< MultiApp > getFromMultiApp() const
Get the MultiApp to transfer data from.
MooseEnum _current_direction
bool _use_nearestpoint_pps
Whether to use a nearest point UserObject to obtain the conservation factor.
AuxVariableName _to_var_name
Given a list of points this object computes the variable integral closest to each one of those points...
virtual void initialSetup()
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
void adjustTransferredSolutionNearestPoint(unsigned int i, FEProblemBase *from_problem, PostprocessorName &from_postprocessor, FEProblemBase &to_problem, PostprocessorName &to_postprocessor)
bool _allow_skipped_adjustment
Whether the adjustment may be skipped when the postprocessor values are 0 / of different signs...
const Parallel::Communicator & comm() const
virtual void postExecute()
Add some extra work if necessary after execute().
const std::shared_ptr< MultiApp > getToMultiApp() const
Get the MultiApp to transfer data to.
bool hasFromMultiApp() const
Whether the transfer owns a non-null from_multi_app.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
void adjustTransferredSolution(FEProblemBase *from_problem, PostprocessorName &from_postprocessor, FEProblemBase &to_problem, PostprocessorName &to_postprocessor)
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
unsigned int variable_number(std::string_view var) const
static InputParameters validParams()
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup...
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
void min(const T &r, T &o, Request &req) const
MultiAppConservativeTransfer(const InputParameters ¶meters)
Intermediary class that allows variable names as inputs.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Real PostprocessorValue
various MOOSE typedefs
const ExecFlagEnum & getExecuteOnEnum() const
Return the execute on MultiMooseEnum for this object.
const std::string & type() const
Get the type of this class.
bool performAdjustment(const PostprocessorValue &from, const PostprocessorValue &to) const
const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name, std::size_t t_index=0) const
Get a read-only reference to the value associated with a Postprocessor that exists.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
std::vector< PostprocessorName > _to_postprocessors_to_be_preserved
Postprocessor evaluates an adjuster for the target physics.
void max(const T &r, T &o, Request &req) const
bool absoluteFuzzyLessEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
Function to check whether a variable is less than or equal to another variable within an absolute tol...
An interface that restricts an object to subdomains via the 'blocks' input parameter.
virtual MooseMesh & mesh() override
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
static InputParameters validParams()
const UserObject & getUserObjectBase(const std::string &name, const THREAD_ID tid=0) const
Get the user object by its name.
virtual void computeUserObjectByName(const ExecFlagType &type, const Moose::AuxGroup &group, const std::string &name)
Compute an user object with the given name.
std::vector< PostprocessorName > _from_postprocessors_to_be_preserved
Postprocessor evaluates an adjuster for the source physics.
SystemBase & sys()
Get the system this variable is part of.
bool _preserve_transfer
If this transfer is going to conserve the physics.