https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MultiAppDofCopyTransfer.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
10// MOOSE includes
12#include "FEProblemBase.h"
13#include "MultiApp.h"
14#include "SystemBase.h"
15
16#include "libmesh/id_types.h"
17#include "libmesh/string_to_enum.h"
18
21{
23
24 params.addParam<TagName>(
25 "from_solution_tag",
26 "The tag of the solution vector to be transferred (default to the solution)");
27 params.addParam<TagName>(
28 "to_solution_tag",
29 "The tag of the solution vector to be transferred to (default to the solution)");
30
31 // Block restrictions
32 params.addParam<std::vector<SubdomainName>>(
33 "from_blocks",
34 {},
35 "Subdomain restriction to transfer from (defaults to all the origin app domain)");
36 params.addParam<std::vector<SubdomainName>>(
37 "to_blocks",
38 {},
39 "Subdomain restriction to transfer to, (defaults to all the target app domain)");
40
42 "Base class for copying degrees-of-freedom values (nonlinear and auxiliary) between apps "
43 "that have identical meshes.");
44 return params;
45}
46
48 : MultiAppFieldTransfer(parameters),
49 _has_block_restrictions(!getParam<std::vector<SubdomainName>>("from_blocks").empty() ||
50 !getParam<std::vector<SubdomainName>>("to_blocks").empty())
51{
52}
53
54void
56{
58
59 const FEProblemBase * from_problem;
60 const FEProblemBase * to_problem;
61
63 {
64 // Subdomain and variable type information is shared on all subapps
65 from_problem = &getFromMultiApp()->appProblemBase(getFromMultiApp()->firstLocalApp());
66 to_problem = &getFromMultiApp()->problemBase();
67 }
69 {
70 from_problem = &getToMultiApp()->problemBase();
71 to_problem = &getToMultiApp()->appProblemBase(getToMultiApp()->firstLocalApp());
72 }
73 else
74 {
75 from_problem = &getFromMultiApp()->appProblemBase(getFromMultiApp()->firstLocalApp());
76 to_problem = &getToMultiApp()->appProblemBase(getToMultiApp()->firstLocalApp());
77 }
78
79 if (from_problem->mesh().getParallelType() != to_problem->mesh().getParallelType())
80 mooseError("The parallel types (distributed or replicated) of the meshes are not the same.");
81
82 // MultiAppDofCopyTransfer-derived transfers copy degree of freedom values directly between
83 // the origin and target solution vectors, so both problems must share the same parallel
84 // decomposition. A common way to violate this is restricting a sub-app's processor count,
85 // e.g. through the MultiApp 'max_procs_per_app' parameter (see idaholab/moose#11045).
86 if (from_problem->comm().size() != to_problem->comm().size())
87 mooseError("The number of processors used by the origin and target problems must be the "
88 "same to use MultiAppDofCopyTransfer-derived transfers. Check that the MultiApp "
89 "'max_procs_per_app' parameter is not restricting sub-apps to a different number "
90 "of processors than the parent app.");
91
92 // Convert block names to block IDs, fill with all blocks if unspecified
94 {
95 const auto & from_block_names = getParam<std::vector<SubdomainName>>("from_blocks");
96 for (const auto & b : from_block_names)
97 if (!MooseMeshUtils::hasSubdomainName(const_cast<MeshBase &>(from_problem->mesh().getMesh()),
98 b))
99 paramError("from_blocks", "The block '", b, "' was not found in the mesh");
100
101 if (from_block_names.size())
102 {
103 if (from_problem)
104 {
105 const auto block_vec = from_problem->mesh().getSubdomainIDs(from_block_names);
106 _from_blocks = std::set<SubdomainID>(block_vec.begin(), block_vec.end());
107 }
108 // We dont even own any of these subapps
109 else
111 }
112 else
113 _from_blocks = from_problem->mesh().meshSubdomains();
114
115 const auto & to_block_names = getParam<std::vector<SubdomainName>>("to_blocks");
116 for (const auto & b : to_block_names)
117 if (!MooseMeshUtils::hasSubdomainName(const_cast<MeshBase &>(to_problem->mesh().getMesh()),
118 b))
119 paramError("to_blocks", "The block '", b, "' was not found in the mesh");
120
121 if (to_block_names.size())
122 {
123 if (to_problem)
124 {
125 const auto block_vec = to_problem->mesh().getSubdomainIDs(to_block_names);
126 _to_blocks = std::set<SubdomainID>(block_vec.begin(), block_vec.end());
127 }
128 // We dont even own any of these subapps
129 else
131 }
132 else
133 _to_blocks = to_problem->mesh().meshSubdomains();
134 }
135
136 // Forbid block restriction on nodal variables as currently not supported
137 if (_from_blocks.size())
138 for (auto & from_var : getFromVarNames())
139 if (from_problem
140 ->getVariable(
142 .hasDoFsOnNodes())
143 paramError("from_blocks", "Block restriction is not implemented for nodal variables");
144 if (_to_blocks.size())
145 for (auto & to_var : getToVarNames())
146 if (to_problem
147 ->getVariable(
149 .hasDoFsOnNodes())
150 paramError("to_blocks", "Block restriction is not implemented for nodal variables");
151}
152
153void
155{
156 // Perform error checking
157 if (!getToVarNames().size())
158 mooseError("No transferred variables were specified, neither programmatically or through the "
159 "'source_variable' parameter");
160 if (getToVarNames().size() != getFromVarNames().size())
161 mooseError("Number of variables transferred must be same in both systems.");
162 for (auto & to_var : getToVarNames())
163 checkVariable(to_problem, to_var);
164 for (auto & from_var : getFromVarNames())
165 checkVariable(from_problem, from_var);
166
167 for (unsigned int v = 0; v < getToVarNames().size(); ++v)
168 {
169 // Populate the to/from variables needed to perform the transfer
170 MooseVariableFEBase & to_var = to_problem.getVariable(
172 MeshBase & to_mesh = to_problem.mesh().getMesh();
173
174 MooseVariableFEBase & from_var = from_problem.getVariable(
176 MeshBase & from_mesh = from_problem.mesh().getMesh();
177
178 auto & to_solution = isParamValid("to_solution_tag")
179 ? to_var.sys().getVector(
180 to_problem.getVectorTagID(getParam<TagName>("to_solution_tag")))
181 : to_var.sys().solution();
182 auto & from_solution = isParamValid("from_solution_tag")
183 ? from_var.sys().getVector(from_problem.getVectorTagID(
184 getParam<TagName>("from_solution_tag")))
185 : from_var.sys().solution();
186
187 // Check integrity
188 if (to_var.feType() != from_var.feType())
189 mooseError("MultiAppFieldTransfer '",
190 name(),
191 "'requires that the target variable '",
192 to_var.name(),
193 "' and the source variable'",
194 from_var.name(),
195 "' must be the same type "
196 "(order and family): ",
197 libMesh::Utility::enum_to_string<FEFamily>(to_var.feType().family),
198 moose::internal::incompatVarMsg(to_var, from_var));
199 if (to_var.fieldType() != from_var.fieldType())
201 "Corresponding transfer variables must be same field type (STANDARD | VECTOR | ARRAY).");
202 if (to_var.count() != from_var.count())
203 mooseError("Corresponding transfer variables must have same number of components.");
204
205 if ((to_mesh.n_nodes() != from_mesh.n_nodes()) || (to_mesh.n_elem() != from_mesh.n_elem()))
206 mooseError("The meshes must be identical to utilize MultiAppDofCopyTransfer::transfer.");
207
208 // Transfer node dofs. Block restriction is not supported, forbidden in initialSetup
209 for (const auto & node : as_range(to_mesh.local_nodes_begin(), to_mesh.local_nodes_end()))
211 node, from_mesh.node_ptr(node->id()), to_var, from_var, to_solution, from_solution);
212
213 // Transfer elem dofs
214 for (auto & to_elem : as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
215 {
216 Elem * from_elem = from_mesh.elem_ptr(to_elem->id());
217 mooseAssert(to_elem->type() == from_elem->type(), "The elements must be the same type.");
218
219 // Examine block restriction
221 {
222 SubdomainID from_block = from_elem->subdomain_id();
223 if (std::find(_from_blocks.begin(), _from_blocks.end(), from_block) == _from_blocks.end())
224 continue;
225
226 SubdomainID to_block = to_elem->subdomain_id();
227 if (std::find(_to_blocks.begin(), _to_blocks.end(), to_block) == _to_blocks.end())
228 continue;
229 }
230
231 transferDofObject(to_elem, from_elem, to_var, from_var, to_solution, from_solution);
232 }
233
234 to_solution.close();
235 to_var.sys().update();
236 }
237}
238
239void
241 libMesh::DofObject * from_object,
242 MooseVariableFEBase & to_var,
243 MooseVariableFEBase & from_var,
244 NumericVector<Number> & to_solution,
245 NumericVector<Number> & from_solution)
246{
247 for (unsigned int vc = 0; vc < to_var.count(); ++vc)
248 // Transfer from one solution vector to another
249 if (to_object->n_dofs(to_var.sys().number(), to_var.number() + vc) >
250 0) // If this variable has dofs at this node
251 for (unsigned int comp = 0;
252 comp < to_object->n_comp(to_var.sys().number(), to_var.number() + vc);
253 ++comp)
254 {
255 dof_id_type dof = to_object->dof_number(to_var.sys().number(), to_var.number() + vc, comp);
256 dof_id_type from_dof =
257 from_object->dof_number(from_var.sys().number(), from_var.number() + vc, comp);
258 Real from_value = from_solution(from_dof);
259 to_solution.set(dof, from_value);
260 }
261}
subdomain_id_type SubdomainID
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
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
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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.
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.
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3557
ParallelType getParallelType() const
Definition MooseMesh.h:1156
std::vector< SubdomainID > getSubdomainIDs(const std::vector< SubdomainName > &subdomain_names) const
Get the associated subdomainIDs for the subdomain names that are passed in.
Definition MooseMesh.C:1729
const std::set< SubdomainID > & meshSubdomains() const
Returns a read-only reference to the set of subdomains currently present in the Mesh.
Definition MooseMesh.C:3280
const libMesh::FEType & feType() const
Get the type of finite element object.
SystemBase & sys()
Get the system this variable is part of.
unsigned int number() const
Get variable number coming from libMesh.
unsigned int count() const
Get the number of components Note: For standard and vector variables, the number is one.
This class provides an interface for common operations on field variables of both FE and FV types wit...
virtual Moose::VarFieldType fieldType() const =0
Field type of this variable.
void transfer(FEProblemBase &to_problem, FEProblemBase &from_problem)
Performs the transfer of a variable between two problems if they have the same mesh.
const bool _has_block_restrictions
Whether block restriction is active.
static InputParameters validParams()
void transferDofObject(libMesh::DofObject *to_object, libMesh::DofObject *from_object, MooseVariableFieldBase &to_var, MooseVariableFieldBase &from_var, NumericVector< Number > &to_solution, NumericVector< Number > &from_solution)
Performs the transfer of values between a node or element.
MultiAppDofCopyTransfer(const InputParameters &parameters)
std::set< SubdomainID > _to_blocks
Subdomain IDs of the blocks to transfer to.
std::set< SubdomainID > _from_blocks
Subdomain IDs of the blocks to transfer from.
void initialSetup() override
Method called at the beginning of the simulation for checking integrity or doing one-time setup.
Intermediary class that allows variable names as inputs.
virtual std::vector< VariableName > getFromVarNames() const =0
Virtual function defining variables to be transferred.
virtual std::vector< AuxVariableName > getToVarNames() const =0
Virtual function defining variables to transfer to.
virtual void initialSetup()
Method called at the beginning of the simulation for checking integrity or doing one-time setup.
static InputParameters validParams()
void checkVariable(const FEProblemBase &fe_problem, const VariableName &var_name, const std::string &param_name="") const
Helper for checking a problem for a variable.
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.
virtual TagID getVectorTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition SubProblem.C:202
unsigned int number() const
Gets the number of this system.
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition SystemBase.C:932
NumericVector< Number > & solution()
Definition SystemBase.h:212
void update()
Update the system (doing libMesh magic)
processor_id_type size() const
@ FROM_MULTIAPP
Definition Transfer.h:71
@ TO_MULTIAPP
Definition Transfer.h:70
MooseEnum _current_direction
Definition Transfer.h:109
unsigned int n_comp(const unsigned int s, const unsigned int var) const
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
unsigned int n_dofs(const unsigned int s, const unsigned int var=libMesh::invalid_uint) const
const Parallel::Communicator & comm() const
bool hasSubdomainName(const MeshBase &input_mesh, const SubdomainName &name)
Whether a particular subdomain name exists in the mesh.
@ VAR_FIELD_ANY
Definition MooseTypes.h:781
@ VAR_ANY
Definition MooseTypes.h:772
const SubdomainID INVALID_BLOCK_ID
Definition MooseTypes.C:20
std::string incompatVarMsg(MooseVariableFieldBase &var1, MooseVariableFieldBase &var2)
Builds and returns a string of the form:
Definition MooseError.C:24