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)
303 if (MooseUtils::absoluteFuzzyLessEqual(from_adjuster, 0.))
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)
419 if (MooseUtils::absoluteFuzzyLessEqual(from_adjuster, 0.))
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");
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Real PostprocessorValue
various MOOSE typedefs
const ExecFlagType EXEC_TRANSFER
An interface that restricts an object to subdomains via the 'blocks' input parameter.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
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.
virtual void computeUserObjectByName(const ExecFlagType &type, const Moose::AuxGroup &group, const std::string &name)
Compute an user object with the given name.
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...
virtual MooseMesh & mesh() override
const UserObject & getUserObjectBase(const std::string &name, const THREAD_ID tid=0) const
Get the user object by its name.
const std::string & type() const
Get the type of this class.
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
SystemBase & sys()
Get the system this variable is part of.
bool performAdjustment(const PostprocessorValue &from, const PostprocessorValue &to) const
std::vector< PostprocessorName > _to_postprocessors_to_be_preserved
Postprocessor evaluates an adjuster for the target physics.
MultiAppConservativeTransfer(const InputParameters ¶meters)
bool _use_nearestpoint_pps
Whether to use a nearest point UserObject to obtain the conservation factor.
std::vector< PostprocessorName > _from_postprocessors_to_be_preserved
Postprocessor evaluates an adjuster for the source physics.
static InputParameters validParams()
virtual void postExecute()
Add some extra work if necessary after execute().
bool _allow_skipped_adjustment
Whether the adjustment may be skipped when the postprocessor values are 0 / of different signs.
bool _preserve_transfer
If this transfer is going to conserve the physics.
virtual void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup.
void adjustTransferredSolution(FEProblemBase *from_problem, PostprocessorName &from_postprocessor, FEProblemBase &to_problem, PostprocessorName &to_postprocessor)
AuxVariableName _to_var_name
void adjustTransferredSolutionNearestPoint(unsigned int i, FEProblemBase *from_problem, PostprocessorName &from_postprocessor, FEProblemBase &to_problem, PostprocessorName &to_postprocessor)
Intermediary class that allows variable names as inputs.
virtual void initialSetup()
Method called at the beginning of the simulation for checking integrity or doing one-time setup.
static InputParameters validParams()
const std::shared_ptr< MultiApp > getToMultiApp() const
Get the MultiApp to transfer data to.
const std::shared_ptr< MultiApp > getFromMultiApp() const
Get the MultiApp to transfer data from.
bool hasFromMultiApp() const
Whether the transfer owns a non-null from_multi_app.
Given a list of points this object computes the variable integral closest to each one of those points...
const ExecFlagEnum & getExecuteOnEnum() const
Return the execute on MultiMooseEnum for this object.
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
void max(const T &r, T &o, Request &req) const
void min(const T &r, T &o, Request &req) const
MooseEnum _current_direction
const Parallel::Communicator & comm() const
unsigned int variable_number(std::string_view var) const