Line data Source code
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
11 : #include "MultiAppDofCopyTransfer.h"
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 :
19 : using namespace libMesh;
20 :
21 : InputParameters
22 15405 : MultiAppDofCopyTransfer::validParams()
23 : {
24 15405 : InputParameters params = MultiAppFieldTransfer::validParams();
25 :
26 15405 : params.addParam<TagName>(
27 : "from_solution_tag",
28 : "The tag of the solution vector to be transferred (default to the solution)");
29 15405 : params.addParam<TagName>(
30 : "to_solution_tag",
31 : "The tag of the solution vector to be transferred to (default to the solution)");
32 :
33 : // Block restrictions
34 15405 : params.addParam<std::vector<SubdomainName>>(
35 : "from_blocks",
36 : {},
37 : "Subdomain restriction to transfer from (defaults to all the origin app domain)");
38 15405 : params.addParam<std::vector<SubdomainName>>(
39 : "to_blocks",
40 : {},
41 : "Subdomain restriction to transfer to, (defaults to all the target app domain)");
42 :
43 15405 : params.addClassDescription(
44 : "Base class for copying degrees-of-freedom values (nonlinear and auxiliary) between apps "
45 : "that have identical meshes.");
46 15405 : return params;
47 0 : }
48 :
49 576 : MultiAppDofCopyTransfer::MultiAppDofCopyTransfer(const InputParameters & parameters)
50 : : MultiAppFieldTransfer(parameters),
51 1652 : _has_block_restrictions(!getParam<std::vector<SubdomainName>>("from_blocks").empty() ||
52 2228 : !getParam<std::vector<SubdomainName>>("to_blocks").empty())
53 : {
54 564 : }
55 :
56 : void
57 528 : MultiAppDofCopyTransfer::initialSetup()
58 : {
59 528 : MultiAppFieldTransfer::initialSetup();
60 :
61 : const FEProblemBase * from_problem;
62 : const FEProblemBase * to_problem;
63 :
64 520 : if (_current_direction == FROM_MULTIAPP)
65 : {
66 : // Subdomain and variable type information is shared on all subapps
67 268 : from_problem = &getFromMultiApp()->appProblemBase(getFromMultiApp()->firstLocalApp());
68 268 : to_problem = &getFromMultiApp()->problemBase();
69 : }
70 252 : else if (_current_direction == TO_MULTIAPP)
71 : {
72 242 : from_problem = &getToMultiApp()->problemBase();
73 242 : to_problem = &getToMultiApp()->appProblemBase(getToMultiApp()->firstLocalApp());
74 : }
75 : else
76 : {
77 10 : from_problem = &getFromMultiApp()->appProblemBase(getFromMultiApp()->firstLocalApp());
78 10 : to_problem = &getToMultiApp()->appProblemBase(getToMultiApp()->firstLocalApp());
79 : }
80 :
81 520 : if (from_problem->mesh().getParallelType() != to_problem->mesh().getParallelType())
82 0 : mooseError("The parallel types (distributed or replicated) of the meshes are not the same.");
83 :
84 : // Convert block names to block IDs, fill with all blocks if unspecified
85 520 : if (_has_block_restrictions)
86 : {
87 76 : const auto & from_block_names = getParam<std::vector<SubdomainName>>("from_blocks");
88 108 : for (const auto & b : from_block_names)
89 40 : if (!MooseMeshUtils::hasSubdomainName(const_cast<MeshBase &>(from_problem->mesh().getMesh()),
90 : b))
91 8 : paramError("from_blocks", "The block '", b, "' was not found in the mesh");
92 :
93 68 : if (from_block_names.size())
94 : {
95 32 : if (from_problem)
96 : {
97 32 : const auto block_vec = from_problem->mesh().getSubdomainIDs(from_block_names);
98 32 : _from_blocks = std::set<SubdomainID>(block_vec.begin(), block_vec.end());
99 32 : }
100 : // We dont even own any of these subapps
101 : else
102 0 : _from_blocks = {Moose::INVALID_BLOCK_ID};
103 : }
104 : else
105 36 : _from_blocks = from_problem->mesh().meshSubdomains();
106 :
107 68 : const auto & to_block_names = getParam<std::vector<SubdomainName>>("to_blocks");
108 96 : for (const auto & b : to_block_names)
109 36 : if (!MooseMeshUtils::hasSubdomainName(const_cast<MeshBase &>(to_problem->mesh().getMesh()),
110 : b))
111 8 : paramError("to_blocks", "The block '", b, "' was not found in the mesh");
112 :
113 60 : if (to_block_names.size())
114 : {
115 28 : if (to_problem)
116 : {
117 28 : const auto block_vec = to_problem->mesh().getSubdomainIDs(to_block_names);
118 28 : _to_blocks = std::set<SubdomainID>(block_vec.begin(), block_vec.end());
119 28 : }
120 : // We dont even own any of these subapps
121 : else
122 0 : _from_blocks = {Moose::INVALID_BLOCK_ID};
123 : }
124 : else
125 32 : _to_blocks = to_problem->mesh().meshSubdomains();
126 : }
127 :
128 : // Forbid block restriction on nodal variables as currently not supported
129 504 : if (_from_blocks.size())
130 112 : for (auto & from_var : getFromVarNames())
131 60 : if (from_problem
132 60 : ->getVariable(
133 : 0, from_var, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY)
134 60 : .hasDoFsOnNodes())
135 60 : paramError("from_blocks", "Block restriction is not implemented for nodal variables");
136 496 : if (_to_blocks.size())
137 104 : for (auto & to_var : getToVarNames())
138 52 : if (to_problem
139 52 : ->getVariable(
140 : 0, to_var, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY)
141 52 : .hasDoFsOnNodes())
142 52 : paramError("to_blocks", "Block restriction is not implemented for nodal variables");
143 496 : }
144 :
145 : void
146 1873 : MultiAppDofCopyTransfer::transfer(FEProblemBase & to_problem, FEProblemBase & from_problem)
147 : {
148 : // Perform error checking
149 1873 : if (!getToVarNames().size())
150 0 : mooseError("No transferred variables were specified, neither programmatically or through the "
151 : "'source_variable' parameter");
152 1873 : if (getToVarNames().size() != getFromVarNames().size())
153 0 : mooseError("Number of variables transferred must be same in both systems.");
154 3757 : for (auto & to_var : getToVarNames())
155 3757 : checkVariable(to_problem, to_var);
156 3753 : for (auto & from_var : getFromVarNames())
157 3753 : checkVariable(from_problem, from_var);
158 :
159 3741 : for (unsigned int v = 0; v < getToVarNames().size(); ++v)
160 : {
161 : // Populate the to/from variables needed to perform the transfer
162 1880 : MooseVariableFEBase & to_var = to_problem.getVariable(
163 3760 : 0, getToVarNames()[v], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
164 1880 : MeshBase & to_mesh = to_problem.mesh().getMesh();
165 :
166 1880 : MooseVariableFEBase & from_var = from_problem.getVariable(
167 3760 : 0, getFromVarNames()[v], Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ANY);
168 1880 : MeshBase & from_mesh = from_problem.mesh().getMesh();
169 :
170 3760 : auto & to_solution = isParamValid("to_solution_tag")
171 3770 : ? to_var.sys().getVector(
172 10 : to_problem.getVectorTagID(getParam<TagName>("to_solution_tag")))
173 1880 : : to_var.sys().solution();
174 3760 : auto & from_solution = isParamValid("from_solution_tag")
175 3760 : ? from_var.sys().getVector(from_problem.getVectorTagID(
176 : getParam<TagName>("from_solution_tag")))
177 1880 : : from_var.sys().solution();
178 :
179 : // Check integrity
180 1880 : if (to_var.feType() != from_var.feType())
181 20 : mooseError("MultiAppFieldTransfer '",
182 4 : name(),
183 : "'requires that the target variable '",
184 4 : to_var.name(),
185 : "' and the source variable'",
186 4 : from_var.name(),
187 : "' must be the same type "
188 : "(order and family): ",
189 4 : libMesh::Utility::enum_to_string<FEFamily>(to_var.feType().family),
190 4 : moose::internal::incompatVarMsg(to_var, from_var));
191 1876 : if (to_var.fieldType() != from_var.fieldType())
192 0 : mooseError(
193 : "Corresponding transfer variables must be same field type (STANDARD | VECTOR | ARRAY).");
194 1876 : if (to_var.count() != from_var.count())
195 0 : mooseError("Corresponding transfer variables must have same number of components.");
196 :
197 1876 : if ((to_mesh.n_nodes() != from_mesh.n_nodes()) || (to_mesh.n_elem() != from_mesh.n_elem()))
198 4 : mooseError("The meshes must be identical to utilize MultiAppDofCopyTransfer::transfer.");
199 :
200 : // Transfer node dofs. Block restriction is not supported, forbidden in initialSetup
201 233206 : for (const auto & node : as_range(to_mesh.local_nodes_begin(), to_mesh.local_nodes_end()))
202 231334 : transferDofObject(
203 233206 : node, from_mesh.node_ptr(node->id()), to_var, from_var, to_solution, from_solution);
204 :
205 : // Transfer elem dofs
206 181884 : for (auto & to_elem : as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
207 : {
208 90006 : Elem * from_elem = from_mesh.elem_ptr(to_elem->id());
209 : mooseAssert(to_elem->type() == from_elem->type(), "The elements must be the same type.");
210 :
211 : // Examine block restriction
212 90006 : if (_has_block_restrictions)
213 : {
214 1024 : SubdomainID from_block = from_elem->subdomain_id();
215 1024 : if (std::find(_from_blocks.begin(), _from_blocks.end(), from_block) == _from_blocks.end())
216 672 : continue;
217 :
218 688 : SubdomainID to_block = to_elem->subdomain_id();
219 688 : if (std::find(_to_blocks.begin(), _to_blocks.end(), to_block) == _to_blocks.end())
220 336 : continue;
221 : }
222 :
223 89334 : transferDofObject(to_elem, from_elem, to_var, from_var, to_solution, from_solution);
224 1872 : }
225 :
226 1872 : to_solution.close();
227 1872 : to_var.sys().update();
228 : }
229 1861 : }
230 :
231 : void
232 205001 : MultiAppDofCopyTransfer::transferDofObject(libMesh::DofObject * to_object,
233 : libMesh::DofObject * from_object,
234 : MooseVariableFEBase & to_var,
235 : MooseVariableFEBase & from_var,
236 : NumericVector<Number> & to_solution,
237 : NumericVector<Number> & from_solution)
238 : {
239 563818 : for (unsigned int vc = 0; vc < to_var.count(); ++vc)
240 : // Transfer from one solution vector to another
241 358817 : if (to_object->n_dofs(to_var.sys().number(), to_var.number() + vc) >
242 : 0) // If this variable has dofs at this node
243 413486 : for (unsigned int comp = 0;
244 413486 : comp < to_object->n_comp(to_var.sys().number(), to_var.number() + vc);
245 : ++comp)
246 : {
247 215671 : dof_id_type dof = to_object->dof_number(to_var.sys().number(), to_var.number() + vc, comp);
248 : dof_id_type from_dof =
249 215671 : from_object->dof_number(from_var.sys().number(), from_var.number() + vc, comp);
250 215671 : Real from_value = from_solution(from_dof);
251 215671 : to_solution.set(dof, from_value);
252 : }
253 205001 : }
|