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 : #include "SubProblem.h"
11 : #include "Factory.h"
12 : #include "MooseMesh.h"
13 : #include "Conversion.h"
14 : #include "Function.h"
15 : #include "MooseApp.h"
16 : #include "MooseVariableFE.h"
17 : #include "MooseArray.h"
18 : #include "Assembly.h"
19 : #include "MooseObjectName.h"
20 : #include "RelationshipManager.h"
21 : #include "MooseUtils.h"
22 : #include "DisplacedSystem.h"
23 : #include "NonlinearSystemBase.h"
24 : #include "LinearSystem.h"
25 :
26 : #include "libmesh/equation_systems.h"
27 : #include "libmesh/system.h"
28 : #include "libmesh/dof_map.h"
29 : #include "libmesh/string_to_enum.h"
30 :
31 : #include <regex>
32 :
33 : using namespace libMesh;
34 :
35 : InputParameters
36 346835 : SubProblem::validParams()
37 : {
38 346835 : InputParameters params = Problem::validParams();
39 :
40 1040505 : params.addParam<bool>(
41 : "default_ghosting",
42 693670 : false,
43 : "Whether or not to use libMesh's default amount of algebraic and geometric ghosting");
44 :
45 346835 : params.addParamNamesToGroup("default_ghosting", "Advanced");
46 :
47 346835 : return params;
48 0 : }
49 :
50 : const std::unordered_set<FEFamily> SubProblem::_default_families_without_p_refinement = {
51 : libMesh::LAGRANGE,
52 : libMesh::NEDELEC_ONE,
53 : libMesh::RAVIART_THOMAS,
54 : libMesh::LAGRANGE_VEC,
55 : libMesh::CLOUGH,
56 : libMesh::BERNSTEIN,
57 : libMesh::RATIONAL_BERNSTEIN};
58 :
59 : // SubProblem /////
60 60037 : SubProblem::SubProblem(const InputParameters & parameters)
61 : : Problem(parameters),
62 60037 : _factory(_app.getFactory()),
63 60037 : _default_ghosting(getParam<bool>("default_ghosting")),
64 60037 : _currently_computing_jacobian(false),
65 60037 : _currently_computing_residual_and_jacobian(false),
66 60037 : _computing_nonlinear_residual(false),
67 60037 : _currently_computing_residual(false),
68 60037 : _safe_access_tagged_matrices(false),
69 60037 : _safe_access_tagged_vectors(false),
70 60037 : _have_ad_objects(false),
71 60037 : _output_functors(false),
72 60037 : _typed_vector_tags(2),
73 240148 : _have_p_refinement(false)
74 : {
75 60037 : unsigned int n_threads = libMesh::n_threads();
76 60037 : _active_elemental_moose_variables.resize(n_threads);
77 60037 : _has_active_elemental_moose_variables.resize(n_threads);
78 :
79 60037 : _active_fe_var_coupleable_matrix_tags.resize(n_threads);
80 60037 : _active_fe_var_coupleable_vector_tags.resize(n_threads);
81 60037 : _active_sc_var_coupleable_matrix_tags.resize(n_threads);
82 60037 : _active_sc_var_coupleable_vector_tags.resize(n_threads);
83 :
84 60037 : _functors.resize(n_threads);
85 60037 : _pbblf_functors.resize(n_threads);
86 60037 : _functor_to_request_info.resize(n_threads);
87 60037 : }
88 :
89 55724 : SubProblem::~SubProblem() {}
90 :
91 : TagID
92 448918 : SubProblem::addVectorTag(const TagName & tag_name,
93 : const Moose::VectorTagType type /* = Moose::VECTOR_TAG_RESIDUAL */)
94 : {
95 448918 : if (type == Moose::VECTOR_TAG_ANY)
96 0 : mooseError("Vector tag type cannot be VECTOR_TAG_ANY");
97 :
98 448918 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
99 :
100 : // First, see if the tag exists already
101 1990345 : for (const auto & vector_tag : _vector_tags)
102 : {
103 : mooseAssert(_vector_tags[vector_tag._id] == vector_tag, "Vector tags index mismatch");
104 1628431 : if (vector_tag._name == tag_name_upper)
105 : {
106 87004 : if (vector_tag._type != type)
107 0 : mooseError("While attempting to add vector tag with name '",
108 : tag_name_upper,
109 : "' and type ",
110 : type,
111 : ",\na tag with the same name but type ",
112 0 : vector_tag._type,
113 : " was found.\n\nA tag can only exist with one type.");
114 :
115 87004 : return vector_tag._id;
116 : }
117 : }
118 :
119 : // Doesn't exist - create it
120 361914 : const TagID new_tag_id = _vector_tags.size();
121 361914 : const TagTypeID new_tag_type_id = _typed_vector_tags[type].size();
122 : // Primary storage for all tags where the index in the vector == the tag ID
123 361914 : _vector_tags.emplace_back(new_tag_id, new_tag_type_id, tag_name_upper, type);
124 : // Secondary storage for each type so that we can have quick access to all tags of a type
125 361914 : _typed_vector_tags[type].emplace_back(new_tag_id, new_tag_type_id, tag_name_upper, type);
126 : // Name map storage for quick name access
127 361914 : _vector_tags_name_map.emplace(tag_name_upper, new_tag_id);
128 :
129 : // Make sure that _vector_tags, _typed_vector_tags, and _vector_tags_name_map are sane
130 361914 : verifyVectorTags();
131 :
132 361914 : return new_tag_id;
133 448918 : }
134 :
135 : bool
136 299537 : SubProblem::vectorTagExists(const TagName & tag_name) const
137 : {
138 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
139 :
140 299537 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
141 2768653 : for (const auto & vector_tag : _vector_tags)
142 2482512 : if (vector_tag._name == tag_name_upper)
143 13396 : return true;
144 :
145 286141 : return false;
146 299537 : }
147 :
148 : void
149 12 : SubProblem::addNotZeroedVectorTag(const TagID tag)
150 : {
151 12 : _not_zeroed_tagged_vectors.insert(tag);
152 12 : }
153 :
154 : bool
155 8774488 : SubProblem::vectorTagNotZeroed(const TagID tag) const
156 : {
157 8774488 : return _not_zeroed_tagged_vectors.count(tag);
158 : }
159 :
160 : const VectorTag &
161 852471610 : SubProblem::getVectorTag(const TagID tag_id) const
162 : {
163 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
164 :
165 852471610 : if (!vectorTagExists(tag_id))
166 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
167 :
168 852471610 : return _vector_tags[tag_id];
169 : }
170 :
171 : std::vector<VectorTag>
172 6097519 : SubProblem::getVectorTags(const std::set<TagID> & tag_ids) const
173 : {
174 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
175 :
176 6097519 : std::vector<VectorTag> tags;
177 6097519 : tags.reserve(tag_ids.size());
178 23663105 : for (const auto & tag_id : tag_ids)
179 17565586 : tags.push_back(getVectorTag(tag_id));
180 6097519 : return tags;
181 0 : }
182 :
183 : const std::vector<VectorTag> &
184 10640447 : SubProblem::getVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
185 : {
186 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
187 :
188 10640447 : if (type == Moose::VECTOR_TAG_ANY)
189 514197 : return _vector_tags;
190 : else
191 10126250 : return _typed_vector_tags[type];
192 : }
193 :
194 : unsigned int
195 7521731 : SubProblem::numVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
196 : {
197 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
198 :
199 7521731 : return getVectorTags(type).size();
200 : }
201 :
202 : TagID
203 6228134 : SubProblem::getVectorTagID(const TagName & tag_name) const
204 : {
205 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
206 :
207 6228134 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
208 6228134 : const auto search = _vector_tags_name_map.find(tag_name_upper);
209 6228134 : if (search != _vector_tags_name_map.end())
210 12456236 : return search->second;
211 :
212 : std::string message =
213 16 : tag_name_upper == "TIME"
214 : ? ".\n\nThis may occur if "
215 : "you have a TimeKernel in your problem but did not specify a transient executioner."
216 32 : : "";
217 16 : mooseError("Vector tag '", tag_name_upper, "' does not exist", message);
218 6228118 : }
219 :
220 : TagName
221 150955 : SubProblem::vectorTagName(const TagID tag_id) const
222 : {
223 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
224 150955 : if (!vectorTagExists(tag_id))
225 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
226 :
227 150955 : return _vector_tags[tag_id]._name;
228 : }
229 :
230 : Moose::VectorTagType
231 2249659875 : SubProblem::vectorTagType(const TagID tag_id) const
232 : {
233 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
234 2249659875 : if (!vectorTagExists(tag_id))
235 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
236 :
237 2249659875 : return _vector_tags[tag_id]._type;
238 : }
239 :
240 : bool
241 361914 : SubProblem::verifyVectorTags() const
242 : {
243 1828248 : for (TagID tag_id = 0; tag_id < _vector_tags.size(); ++tag_id)
244 : {
245 1466334 : const auto & vector_tag = _vector_tags[tag_id];
246 :
247 1466334 : if (vector_tag._id != tag_id)
248 0 : mooseError("Vector tag ", vector_tag._id, " id mismatch in _vector_tags");
249 1466334 : if (vector_tag._type == Moose::VECTOR_TAG_ANY)
250 0 : mooseError("Vector tag '", vector_tag._name, "' has type VECTOR_TAG_ANY");
251 :
252 1466334 : const auto search = _vector_tags_name_map.find(vector_tag._name);
253 1466334 : if (search == _vector_tags_name_map.end())
254 0 : mooseError("Vector tag ", vector_tag._id, " is not in _vector_tags_name_map");
255 1466334 : else if (search->second != tag_id)
256 0 : mooseError("Vector tag ", vector_tag._id, " has incorrect id in _vector_tags_name_map");
257 :
258 1466334 : unsigned int found_in_type = 0;
259 6055406 : for (TagTypeID tag_type_id = 0; tag_type_id < _typed_vector_tags[vector_tag._type].size();
260 : ++tag_type_id)
261 : {
262 4589072 : const auto & vector_tag_type = _typed_vector_tags[vector_tag._type][tag_type_id];
263 4589072 : if (vector_tag_type == vector_tag)
264 : {
265 1466334 : ++found_in_type;
266 1466334 : if (vector_tag_type._type_id != tag_type_id)
267 0 : mooseError("Type ID for Vector tag ", tag_id, " is incorrect");
268 : }
269 : }
270 :
271 1466334 : if (found_in_type == 0)
272 0 : mooseError("Vector tag ", tag_id, " not found in _typed_vector_tags");
273 1466334 : if (found_in_type > 1)
274 0 : mooseError("Vector tag ", tag_id, " found multiple times in _typed_vector_tags");
275 : }
276 :
277 361914 : unsigned int num_typed_vector_tags = 0;
278 1085742 : for (const auto & typed_vector_tags : _typed_vector_tags)
279 723828 : num_typed_vector_tags += typed_vector_tags.size();
280 361914 : if (num_typed_vector_tags != _vector_tags.size())
281 0 : mooseError("Size mismatch between _vector_tags and _typed_vector_tags");
282 361914 : if (_vector_tags_name_map.size() != _vector_tags.size())
283 0 : mooseError("Size mismatch between _vector_tags and _vector_tags_name_map");
284 :
285 361914 : return true;
286 : }
287 :
288 : void
289 3016381 : SubProblem::selectVectorTagsFromSystem(const SystemBase & system,
290 : const std::vector<VectorTag> & input_vector_tags,
291 : std::set<TagID> & selected_tags)
292 : {
293 3016381 : selected_tags.clear();
294 11745316 : for (const auto & vector_tag : input_vector_tags)
295 8728935 : if (system.hasVector(vector_tag._id))
296 8728533 : selected_tags.insert(vector_tag._id);
297 3016381 : }
298 :
299 : void
300 4957 : SubProblem::selectMatrixTagsFromSystem(const SystemBase & system,
301 : const std::map<TagName, TagID> & input_matrix_tags,
302 : std::set<TagID> & selected_tags)
303 : {
304 4957 : selected_tags.clear();
305 10028 : for (const auto & matrix_tag_pair : input_matrix_tags)
306 5071 : if (system.hasMatrix(matrix_tag_pair.second))
307 4979 : selected_tags.insert(matrix_tag_pair.second);
308 4957 : }
309 :
310 : TagID
311 117315 : SubProblem::addMatrixTag(TagName tag_name)
312 : {
313 117315 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
314 117315 : auto existing_tag = _matrix_tag_name_to_tag_id.find(tag_name_upper);
315 117315 : if (existing_tag == _matrix_tag_name_to_tag_id.end())
316 : {
317 116841 : auto tag_id = _matrix_tag_name_to_tag_id.size();
318 :
319 116841 : _matrix_tag_name_to_tag_id[tag_name_upper] = tag_id;
320 :
321 116841 : _matrix_tag_id_to_tag_name[tag_id] = tag_name_upper;
322 : }
323 :
324 234630 : return _matrix_tag_name_to_tag_id.at(tag_name_upper);
325 117315 : }
326 :
327 : bool
328 277582 : SubProblem::matrixTagExists(const TagName & tag_name) const
329 : {
330 277582 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
331 :
332 555164 : return _matrix_tag_name_to_tag_id.find(tag_name_upper) != _matrix_tag_name_to_tag_id.end();
333 277582 : }
334 :
335 : bool
336 1511780 : SubProblem::matrixTagExists(TagID tag_id) const
337 : {
338 1511780 : return _matrix_tag_id_to_tag_name.find(tag_id) != _matrix_tag_id_to_tag_name.end();
339 : }
340 :
341 : TagID
342 276310 : SubProblem::getMatrixTagID(const TagName & tag_name) const
343 : {
344 276310 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
345 :
346 276310 : if (!matrixTagExists(tag_name))
347 4 : mooseError("Matrix tag: ",
348 : tag_name,
349 : " does not exist. ",
350 : "If this is a TimeKernel then this may have happened because you didn't "
351 : "specify a Transient Executioner.");
352 :
353 552612 : return _matrix_tag_name_to_tag_id.at(tag_name_upper);
354 276306 : }
355 :
356 : TagName
357 320 : SubProblem::matrixTagName(TagID tag)
358 : {
359 320 : return _matrix_tag_id_to_tag_name[tag];
360 : }
361 :
362 : void
363 578020 : SubProblem::setActiveFEVariableCoupleableMatrixTags(std::set<TagID> & mtags, const THREAD_ID tid)
364 : {
365 578020 : _active_fe_var_coupleable_matrix_tags[tid] = mtags;
366 578020 : }
367 :
368 : void
369 6812400 : SubProblem::setActiveFEVariableCoupleableVectorTags(std::set<TagID> & vtags, const THREAD_ID tid)
370 : {
371 6812400 : _active_fe_var_coupleable_vector_tags[tid] = vtags;
372 13746547 : for (const auto sys_num : make_range(numSolverSystems()))
373 6934147 : systemBaseSolver(sys_num).setActiveVariableCoupleableVectorTags(vtags, tid);
374 6812400 : systemBaseAuxiliary().setActiveVariableCoupleableVectorTags(vtags, tid);
375 6812400 : }
376 :
377 : void
378 271881 : SubProblem::clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
379 : {
380 271881 : _active_fe_var_coupleable_vector_tags[tid].clear();
381 271881 : }
382 :
383 : void
384 271881 : SubProblem::clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
385 : {
386 271881 : _active_fe_var_coupleable_matrix_tags[tid].clear();
387 271881 : }
388 :
389 : const std::set<TagID> &
390 1746655551 : SubProblem::getActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid) const
391 : {
392 1746655551 : return _active_fe_var_coupleable_matrix_tags[tid];
393 : }
394 :
395 : const std::set<TagID> &
396 292 : SubProblem::getActiveFEVariableCoupleableVectorTags(const THREAD_ID tid) const
397 : {
398 292 : return _active_fe_var_coupleable_vector_tags[tid];
399 : }
400 :
401 : void
402 49884 : SubProblem::setActiveScalarVariableCoupleableMatrixTags(std::set<TagID> & mtags,
403 : const THREAD_ID tid)
404 : {
405 49884 : _active_sc_var_coupleable_matrix_tags[tid] = mtags;
406 49884 : }
407 :
408 : void
409 49884 : SubProblem::setActiveScalarVariableCoupleableVectorTags(std::set<TagID> & vtags,
410 : const THREAD_ID tid)
411 : {
412 49884 : _active_sc_var_coupleable_vector_tags[tid] = vtags;
413 99768 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
414 49884 : systemBaseNonlinear(nl_sys_num).setActiveScalarVariableCoupleableVectorTags(vtags, tid);
415 49884 : systemBaseAuxiliary().setActiveScalarVariableCoupleableVectorTags(vtags, tid);
416 49884 : }
417 :
418 : void
419 49884 : SubProblem::clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid)
420 : {
421 49884 : _active_sc_var_coupleable_vector_tags[tid].clear();
422 49884 : }
423 :
424 : void
425 49884 : SubProblem::clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid)
426 : {
427 49884 : _active_sc_var_coupleable_matrix_tags[tid].clear();
428 49884 : }
429 :
430 : const std::set<TagID> &
431 520509 : SubProblem::getActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) const
432 : {
433 520509 : return _active_sc_var_coupleable_matrix_tags[tid];
434 : }
435 :
436 : const std::set<TagID> &
437 0 : SubProblem::getActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid) const
438 : {
439 0 : return _active_sc_var_coupleable_vector_tags[tid];
440 : }
441 :
442 : void
443 10549638 : SubProblem::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
444 : const THREAD_ID tid)
445 : {
446 10549638 : if (!moose_vars.empty())
447 : {
448 10238913 : _has_active_elemental_moose_variables[tid] = 1;
449 10238913 : _active_elemental_moose_variables[tid] = moose_vars;
450 : }
451 10549638 : }
452 :
453 : const std::set<MooseVariableFEBase *> &
454 1141584772 : SubProblem::getActiveElementalMooseVariables(const THREAD_ID tid) const
455 : {
456 1141584772 : return _active_elemental_moose_variables[tid];
457 : }
458 :
459 : bool
460 1182244439 : SubProblem::hasActiveElementalMooseVariables(const THREAD_ID tid) const
461 : {
462 1182244439 : return _has_active_elemental_moose_variables[tid];
463 : }
464 :
465 : void
466 4506287 : SubProblem::clearActiveElementalMooseVariables(const THREAD_ID tid)
467 : {
468 4506287 : _has_active_elemental_moose_variables[tid] = 0;
469 4506287 : _active_elemental_moose_variables[tid].clear();
470 4506287 : }
471 :
472 : std::set<SubdomainID>
473 8 : SubProblem::getMaterialPropertyBlocks(const std::string & prop_name)
474 : {
475 8 : std::set<SubdomainID> blocks;
476 :
477 24 : for (const auto & it : _map_block_material_props)
478 : {
479 16 : const std::set<std::string> & prop_names = it.second;
480 16 : std::set<std::string>::iterator name_it = prop_names.find(prop_name);
481 16 : if (name_it != prop_names.end())
482 16 : blocks.insert(it.first);
483 : }
484 :
485 8 : return blocks;
486 0 : }
487 :
488 : std::vector<SubdomainName>
489 8 : SubProblem::getMaterialPropertyBlockNames(const std::string & prop_name)
490 : {
491 8 : std::set<SubdomainID> blocks = getMaterialPropertyBlocks(prop_name);
492 8 : std::vector<SubdomainName> block_names;
493 8 : block_names.reserve(blocks.size());
494 24 : for (const auto & block_id : blocks)
495 : {
496 16 : SubdomainName name;
497 16 : name = mesh().getMesh().subdomain_name(block_id);
498 16 : if (name.empty())
499 : {
500 8 : std::ostringstream oss;
501 8 : oss << block_id;
502 8 : name = oss.str();
503 8 : }
504 16 : block_names.push_back(name);
505 16 : }
506 :
507 16 : return block_names;
508 8 : }
509 :
510 : bool
511 320 : SubProblem::hasBlockMaterialProperty(SubdomainID bid, const std::string & prop_name)
512 : {
513 320 : auto it = _map_block_material_props.find(bid);
514 320 : if (it == _map_block_material_props.end())
515 0 : return false;
516 :
517 320 : if (it->second.count(prop_name) > 0)
518 240 : return true;
519 : else
520 80 : return false;
521 : }
522 :
523 : // TODO: remove code duplication by templating
524 : std::set<BoundaryID>
525 8 : SubProblem::getMaterialPropertyBoundaryIDs(const std::string & prop_name)
526 : {
527 8 : std::set<BoundaryID> boundaries;
528 :
529 20 : for (const auto & it : _map_boundary_material_props)
530 : {
531 12 : const std::set<std::string> & prop_names = it.second;
532 12 : std::set<std::string>::iterator name_it = prop_names.find(prop_name);
533 12 : if (name_it != prop_names.end())
534 12 : boundaries.insert(it.first);
535 : }
536 :
537 8 : return boundaries;
538 0 : }
539 :
540 : std::vector<BoundaryName>
541 8 : SubProblem::getMaterialPropertyBoundaryNames(const std::string & prop_name)
542 : {
543 8 : std::set<BoundaryID> boundaries = getMaterialPropertyBoundaryIDs(prop_name);
544 8 : std::vector<BoundaryName> boundary_names;
545 8 : boundary_names.reserve(boundaries.size());
546 8 : const BoundaryInfo & boundary_info = mesh().getMesh().get_boundary_info();
547 :
548 20 : for (const auto & bnd_id : boundaries)
549 : {
550 12 : BoundaryName name;
551 12 : if (bnd_id == Moose::ANY_BOUNDARY_ID)
552 4 : name = "ANY_BOUNDARY_ID";
553 : else
554 : {
555 8 : name = boundary_info.get_sideset_name(bnd_id);
556 8 : if (name.empty())
557 : {
558 0 : std::ostringstream oss;
559 0 : oss << bnd_id;
560 0 : name = oss.str();
561 0 : }
562 : }
563 12 : boundary_names.push_back(name);
564 12 : }
565 :
566 16 : return boundary_names;
567 8 : }
568 :
569 : bool
570 0 : SubProblem::hasBoundaryMaterialProperty(BoundaryID bid, const std::string & prop_name)
571 : {
572 0 : auto it = _map_boundary_material_props.find(bid);
573 0 : if (it == _map_boundary_material_props.end())
574 0 : return false;
575 :
576 0 : if (it->second.count(prop_name) > 0)
577 0 : return true;
578 : else
579 0 : return false;
580 : }
581 :
582 : void
583 63388 : SubProblem::storeSubdomainMatPropName(SubdomainID block_id, const std::string & name)
584 : {
585 63388 : _map_block_material_props[block_id].insert(name);
586 63388 : }
587 :
588 : void
589 59667 : SubProblem::storeBoundaryMatPropName(BoundaryID boundary_id, const std::string & name)
590 : {
591 59667 : _map_boundary_material_props[boundary_id].insert(name);
592 59667 : }
593 :
594 : void
595 8799 : SubProblem::storeSubdomainZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name)
596 : {
597 8799 : _zero_block_material_props[block_id].insert(name);
598 8799 : }
599 :
600 : void
601 8799 : SubProblem::storeBoundaryZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name)
602 : {
603 8799 : _zero_boundary_material_props[boundary_id].insert(name);
604 8799 : }
605 :
606 : void
607 42717 : SubProblem::storeSubdomainDelayedCheckMatProp(const std::string & requestor,
608 : SubdomainID block_id,
609 : const std::string & name)
610 : {
611 42717 : _map_block_material_props_check[block_id].insert(std::make_pair(requestor, name));
612 42717 : }
613 :
614 : void
615 5855 : SubProblem::storeBoundaryDelayedCheckMatProp(const std::string & requestor,
616 : BoundaryID boundary_id,
617 : const std::string & name)
618 : {
619 5855 : _map_boundary_material_props_check[boundary_id].insert(std::make_pair(requestor, name));
620 5855 : }
621 :
622 : void
623 56015 : SubProblem::checkBlockMatProps()
624 : {
625 : // Variable for storing all available blocks/boundaries from the mesh
626 56015 : std::set<SubdomainID> all_ids(mesh().meshSubdomains());
627 :
628 56015 : std::stringstream errors;
629 :
630 : // Loop through the properties to check
631 61591 : for (const auto & check_it : _map_block_material_props_check)
632 : {
633 : // The current id for the property being checked (BoundaryID || BlockID)
634 5576 : SubdomainID check_id = check_it.first;
635 :
636 5576 : std::set<SubdomainID> check_ids = {check_id};
637 :
638 : // Loop through all the block/boundary ids
639 11152 : for (const auto & id : check_ids)
640 : {
641 : // Loop through all the stored properties
642 46066 : for (const auto & prop_it : check_it.second)
643 : {
644 : // Produce an error if the material property is not defined on the current block/boundary
645 : // and any block/boundary
646 : // and not is not a zero material property.
647 40592 : if (_map_block_material_props[id].count(prop_it.second) == 0 &&
648 40592 : _zero_block_material_props[id].count(prop_it.second) == 0)
649 : {
650 50 : std::string check_name = restrictionSubdomainCheckName(id);
651 50 : if (check_name.empty())
652 45 : check_name = std::to_string(id);
653 100 : errors << "Material property '" << prop_it.second << "', requested by '" << prop_it.first
654 50 : << "' is not defined on block " << check_name << "\n";
655 50 : }
656 : }
657 : }
658 5576 : }
659 :
660 56015 : if (!errors.str().empty())
661 40 : mooseError(errors.str());
662 55975 : }
663 :
664 : void
665 55975 : SubProblem::checkBoundaryMatProps()
666 : {
667 : // Variable for storing the value for ANY_BOUNDARY_ID
668 55975 : BoundaryID any_id = Moose::ANY_BOUNDARY_ID;
669 :
670 : // Variable for storing all available blocks/boundaries from the mesh
671 55975 : std::set<BoundaryID> all_ids(mesh().getBoundaryIDs());
672 :
673 55975 : std::stringstream errors;
674 :
675 : // Loop through the properties to check
676 58456 : for (const auto & check_it : _map_boundary_material_props_check)
677 : {
678 : // The current id for the property being checked (BoundaryID || BlockID)
679 2481 : BoundaryID check_id = check_it.first;
680 :
681 : // In the case when the material being checked has an ID is set to ANY, then loop through all
682 : // the possible ids and verify that the material property is defined.
683 2481 : std::set<BoundaryID> check_ids{check_id};
684 2481 : if (check_id == any_id)
685 0 : check_ids = all_ids;
686 :
687 : // Loop through all the block/boundary ids
688 4962 : for (const auto & id : check_ids)
689 : {
690 : // Loop through all the stored properties
691 8336 : for (const auto & prop_it : check_it.second)
692 : {
693 : // Produce an error if the material property is not defined on the current block/boundary
694 : // and any block/boundary
695 : // and not is not a zero material property.
696 5855 : if (_map_boundary_material_props[id].count(prop_it.second) == 0 &&
697 4651 : _map_boundary_material_props[any_id].count(prop_it.second) == 0 &&
698 22231 : _zero_boundary_material_props[id].count(prop_it.second) == 0 &&
699 5870 : _zero_boundary_material_props[any_id].count(prop_it.second) == 0)
700 : {
701 15 : std::string check_name = restrictionBoundaryCheckName(id);
702 15 : if (check_name.empty())
703 0 : check_name = std::to_string(id);
704 30 : errors << "Material property '" << prop_it.second << "', requested by '" << prop_it.first
705 15 : << "' is not defined on boundary " << check_name << "\n";
706 15 : }
707 : }
708 : }
709 2481 : }
710 :
711 55975 : if (!errors.str().empty())
712 12 : mooseError(errors.str());
713 55963 : }
714 :
715 : bool
716 0 : SubProblem::nlConverged(const unsigned int nl_sys_num)
717 : {
718 : mooseAssert(nl_sys_num < numNonlinearSystems(),
719 : "The nonlinear system number is higher than the number of systems we have!");
720 0 : return solverSystemConverged(nl_sys_num);
721 : }
722 :
723 : void
724 60200 : SubProblem::markMatPropRequested(const std::string & prop_name)
725 : {
726 60200 : _material_property_requested.insert(prop_name);
727 60200 : }
728 :
729 : bool
730 0 : SubProblem::isMatPropRequested(const std::string & prop_name) const
731 : {
732 0 : return _material_property_requested.find(prop_name) != _material_property_requested.end();
733 : }
734 :
735 : void
736 47051 : SubProblem::addConsumedPropertyName(const MooseObjectName & obj_name, const std::string & prop_name)
737 : {
738 47051 : _consumed_material_properties[obj_name].insert(prop_name);
739 47051 : }
740 :
741 : const std::map<MooseObjectName, std::set<std::string>> &
742 202 : SubProblem::getConsumedPropertyMap() const
743 : {
744 202 : return _consumed_material_properties;
745 : }
746 :
747 : DiracKernelInfo &
748 950 : SubProblem::diracKernelInfo()
749 : {
750 950 : return _dirac_kernel_info;
751 : }
752 :
753 : Real
754 0 : SubProblem::finalNonlinearResidual(unsigned int) const
755 : {
756 0 : return 0;
757 : }
758 :
759 : unsigned int
760 0 : SubProblem::nNonlinearIterations(unsigned int) const
761 : {
762 0 : return 0;
763 : }
764 :
765 : unsigned int
766 0 : SubProblem::nLinearIterations(unsigned int) const
767 : {
768 0 : return 0;
769 : }
770 :
771 : std::string
772 50 : SubProblem::restrictionSubdomainCheckName(SubdomainID check_id)
773 : {
774 : // TODO: Put a better a interface in MOOSE
775 50 : std::map<subdomain_id_type, std::string> & name_map = mesh().getMesh().set_subdomain_name_map();
776 50 : std::map<subdomain_id_type, std::string>::const_iterator pos = name_map.find(check_id);
777 50 : if (pos != name_map.end())
778 5 : return pos->second;
779 45 : return "";
780 : }
781 :
782 : std::string
783 15 : SubProblem::restrictionBoundaryCheckName(BoundaryID check_id)
784 : {
785 15 : return mesh().getMesh().get_boundary_info().sideset_name(check_id);
786 : }
787 :
788 : void
789 129178178 : SubProblem::setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid)
790 : {
791 259524674 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
792 130346496 : assembly(tid, nl_sys_num).setCurrentBoundaryID(bid);
793 129178178 : }
794 :
795 : unsigned int
796 192 : SubProblem::getAxisymmetricRadialCoord() const
797 : {
798 192 : return mesh().getAxisymmetricRadialCoord();
799 : }
800 :
801 : bool
802 4 : SubProblem::hasLinearVariable(const std::string & var_name) const
803 : {
804 4 : for (const auto i : make_range(numLinearSystems()))
805 0 : if (systemBaseLinear(i).hasVariable(var_name))
806 0 : return true;
807 4 : return false;
808 : }
809 :
810 : bool
811 17 : SubProblem::hasAuxiliaryVariable(const std::string & var_name) const
812 : {
813 17 : return systemBaseAuxiliary().hasVariable(var_name);
814 : }
815 :
816 : template <typename T>
817 : MooseVariableFEBase &
818 4319806 : SubProblem::getVariableHelper(const THREAD_ID tid,
819 : const std::string & var_name,
820 : Moose::VarKindType expected_var_type,
821 : Moose::VarFieldType expected_var_field_type,
822 : const std::vector<T> & systems,
823 : const SystemBase & aux) const
824 : {
825 : // Eventual return value
826 4319806 : MooseVariableFEBase * var = nullptr;
827 :
828 4319806 : const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
829 :
830 : // First check that the variable is found on the expected system.
831 4319806 : if (expected_var_type == Moose::VarKindType::VAR_ANY)
832 : {
833 2383231 : if (var_in_sys)
834 1085117 : var = &(systems[sys_num]->getVariable(tid, var_name));
835 1298114 : else if (aux.hasVariable(var_name))
836 1298114 : var = &(aux.getVariable(tid, var_name));
837 : else
838 0 : mooseError("Unknown variable " + var_name);
839 : }
840 2115519 : else if (expected_var_type == Moose::VarKindType::VAR_SOLVER && var_in_sys &&
841 178944 : systems[sys_num]->hasVariable(var_name))
842 178944 : var = &(systems[sys_num]->getVariable(tid, var_name));
843 1757631 : else if (expected_var_type == Moose::VarKindType::VAR_AUXILIARY && aux.hasVariable(var_name))
844 1757631 : var = &(aux.getVariable(tid, var_name));
845 : else
846 : {
847 0 : std::string expected_var_type_string =
848 : (expected_var_type == Moose::VarKindType::VAR_SOLVER ? "nonlinear" : "auxiliary");
849 0 : mooseError("No ",
850 : expected_var_type_string,
851 : " variable named ",
852 : var_name,
853 : " found. "
854 : "Did you specify an auxiliary variable when you meant to specify a nonlinear "
855 : "variable (or vice-versa)?");
856 0 : }
857 :
858 : // Now make sure the var found has the expected field type.
859 6313965 : if ((expected_var_field_type == Moose::VarFieldType::VAR_FIELD_ANY) ||
860 1994159 : (expected_var_field_type == var->fieldType()))
861 4319798 : return *var;
862 : else
863 : {
864 8 : std::string expected_var_field_type_string =
865 : MooseUtils::toLower(Moose::stringify(expected_var_field_type));
866 8 : std::string var_field_type_string = MooseUtils::toLower(Moose::stringify(var->fieldType()));
867 :
868 8 : mooseError("No ",
869 : expected_var_field_type_string,
870 : " variable named ",
871 : var_name,
872 : " found. "
873 : "Did you specify a ",
874 : var_field_type_string,
875 : " variable when you meant to specify a ",
876 : expected_var_field_type_string,
877 : " variable?");
878 0 : }
879 : }
880 :
881 : void
882 283554 : SubProblem::reinitElemFaceRef(const Elem * elem,
883 : unsigned int side,
884 : Real tolerance,
885 : const std::vector<Point> * const pts,
886 : const std::vector<Real> * const weights,
887 : const THREAD_ID tid)
888 : {
889 567108 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
890 : {
891 : // - Set our _current_elem for proper dof index getting in the moose variables
892 : // - Reinitialize all of our FE objects so we have current phi, dphi, etc. data
893 : // Note that our number of shape functions will reflect the number of shapes associated with the
894 : // interior element while the number of quadrature points will be determined by the passed pts
895 : // parameter (which presumably will have a number of pts reflective of a facial quadrature rule)
896 283554 : assembly(tid, nl_sys_num).reinitElemFaceRef(elem, side, tolerance, pts, weights);
897 :
898 283554 : auto & nl = systemBaseNonlinear(nl_sys_num);
899 :
900 : // Actually get the dof indices in the moose variables
901 283554 : nl.prepare(tid);
902 :
903 : // Let's finally compute our variable values!
904 283554 : nl.reinitElemFace(elem, side, tid);
905 : }
906 :
907 : // do same for aux as for nl
908 283554 : systemBaseAuxiliary().prepare(tid);
909 283554 : systemBaseAuxiliary().reinitElemFace(elem, side, tid);
910 :
911 : // With the dof indices set in the moose variables, now let's properly size
912 : // our local residuals/Jacobians
913 283554 : auto & current_assembly = assembly(tid, currentNlSysNum());
914 283554 : if (currentlyComputingJacobian() || currentlyComputingResidualAndJacobian())
915 92752 : current_assembly.prepareJacobianBlock();
916 283554 : if (!currentlyComputingJacobian())
917 190802 : current_assembly.prepareResidual();
918 283554 : }
919 :
920 : void
921 283554 : SubProblem::reinitNeighborFaceRef(const Elem * neighbor_elem,
922 : unsigned int neighbor_side,
923 : Real tolerance,
924 : const std::vector<Point> * const pts,
925 : const std::vector<Real> * const weights,
926 : const THREAD_ID tid)
927 : {
928 567108 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
929 : {
930 : // - Set our _current_neighbor_elem for proper dof index getting in the moose variables
931 : // - Reinitialize all of our FE objects so we have current phi, dphi, etc. data
932 : // Note that our number of shape functions will reflect the number of shapes associated with the
933 : // interior element while the number of quadrature points will be determined by the passed pts
934 : // parameter (which presumably will have a number of pts reflective of a facial quadrature rule)
935 283554 : assembly(tid, nl_sys_num)
936 283554 : .reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights);
937 :
938 283554 : auto & nl = systemBaseNonlinear(nl_sys_num);
939 :
940 : // Actually get the dof indices in the moose variables
941 283554 : nl.prepareNeighbor(tid);
942 :
943 : // Let's finally compute our variable values!
944 283554 : nl.reinitNeighborFace(neighbor_elem, neighbor_side, tid);
945 : }
946 :
947 : // do same for aux as for nl
948 283554 : systemBaseAuxiliary().prepareNeighbor(tid);
949 283554 : systemBaseAuxiliary().reinitNeighborFace(neighbor_elem, neighbor_side, tid);
950 :
951 : // With the dof indices set in the moose variables, now let's properly size
952 : // our local residuals/Jacobians
953 283554 : assembly(tid, currentNlSysNum()).prepareNeighbor();
954 283554 : }
955 :
956 : void
957 299795 : SubProblem::reinitLowerDElem(const Elem * elem,
958 : const THREAD_ID tid,
959 : const std::vector<Point> * const pts,
960 : const std::vector<Real> * const weights)
961 : {
962 599590 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
963 : {
964 : // - Set our _current_lower_d_elem for proper dof index getting in the moose variables
965 : // - Reinitialize all of our lower-d FE objects so we have current phi, dphi, etc. data
966 299795 : assembly(tid, nl_sys_num).reinitLowerDElem(elem, pts, weights);
967 :
968 299795 : auto & nl = systemBaseNonlinear(nl_sys_num);
969 :
970 : // Actually get the dof indices in the moose variables
971 299795 : nl.prepareLowerD(tid);
972 :
973 : // With the dof indices set in the moose variables, now let's properly size
974 : // our local residuals/Jacobians
975 299795 : assembly(tid, nl_sys_num).prepareLowerD();
976 :
977 : // Let's finally compute our variable values!
978 299795 : nl.reinitLowerD(tid);
979 : }
980 :
981 : // do same for aux as for nl
982 299795 : systemBaseAuxiliary().prepareLowerD(tid);
983 299795 : systemBaseAuxiliary().reinitLowerD(tid);
984 299795 : }
985 :
986 : void
987 263086 : SubProblem::reinitNeighborLowerDElem(const Elem * elem, const THREAD_ID tid)
988 : {
989 526172 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
990 263086 : assembly(tid, nl_sys_num).reinitNeighborLowerDElem(elem);
991 263086 : }
992 :
993 : void
994 526172 : SubProblem::reinitMortarElem(const Elem * elem, const THREAD_ID tid)
995 : {
996 1052344 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
997 526172 : assembly(tid, nl_sys_num).reinitMortarElem(elem);
998 526172 : }
999 :
1000 : void
1001 30994 : SubProblem::cloneAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
1002 : {
1003 30994 : EquationSystems & eq = es();
1004 30994 : const auto n_sys = eq.n_systems();
1005 :
1006 61988 : auto pr = _root_alg_gf_to_sys_clones.emplace(
1007 30994 : &algebraic_gf, std::vector<std::shared_ptr<GhostingFunctor>>(n_sys - 1));
1008 : mooseAssert(pr.second, "We are adding a duplicate algebraic ghosting functor");
1009 30994 : auto & clones_vec = pr.first->second;
1010 :
1011 62138 : for (MooseIndex(n_sys) i = 1; i < n_sys; ++i)
1012 : {
1013 31144 : DofMap & dof_map = eq.get_system(i).get_dof_map();
1014 31144 : std::shared_ptr<GhostingFunctor> clone_alg_gf = algebraic_gf.clone();
1015 62288 : std::dynamic_pointer_cast<RelationshipManager>(clone_alg_gf)
1016 31144 : ->init(mesh(), *algebraic_gf.get_mesh(), &dof_map);
1017 31144 : dof_map.add_algebraic_ghosting_functor(clone_alg_gf, to_mesh);
1018 31144 : clones_vec[i - 1] = clone_alg_gf;
1019 31144 : }
1020 30994 : }
1021 :
1022 : void
1023 30994 : SubProblem::addAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
1024 : {
1025 30994 : EquationSystems & eq = es();
1026 30994 : const auto n_sys = eq.n_systems();
1027 30994 : if (!n_sys)
1028 0 : return;
1029 :
1030 30994 : eq.get_system(0).get_dof_map().add_algebraic_ghosting_functor(algebraic_gf, to_mesh);
1031 30994 : cloneAlgebraicGhostingFunctor(algebraic_gf, to_mesh);
1032 : }
1033 :
1034 : void
1035 42328 : SubProblem::cloneCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
1036 : {
1037 42328 : const std::size_t num_nl_sys = numNonlinearSystems();
1038 :
1039 84656 : auto pr = _root_coupling_gf_to_sys_clones.emplace(
1040 42328 : &coupling_gf, std::vector<std::shared_ptr<GhostingFunctor>>(num_nl_sys - 1));
1041 : mooseAssert(pr.second, "We are adding a duplicate coupling functor");
1042 42328 : auto & clones_vec = pr.first->second;
1043 :
1044 42514 : for (const auto i : make_range(std::size_t(1), num_nl_sys))
1045 : {
1046 186 : DofMap & dof_map = systemBaseNonlinear(i).system().get_dof_map();
1047 186 : std::shared_ptr<GhostingFunctor> clone_coupling_gf = coupling_gf.clone();
1048 372 : std::dynamic_pointer_cast<RelationshipManager>(clone_coupling_gf)
1049 186 : ->init(mesh(), *coupling_gf.get_mesh(), &dof_map);
1050 186 : dof_map.add_coupling_functor(clone_coupling_gf, to_mesh);
1051 186 : clones_vec[i - 1] = clone_coupling_gf;
1052 186 : }
1053 42328 : }
1054 :
1055 : void
1056 43413 : SubProblem::addCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
1057 : {
1058 43413 : const auto num_nl_sys = numNonlinearSystems();
1059 43413 : if (!num_nl_sys)
1060 1085 : return;
1061 :
1062 42328 : systemBaseNonlinear(0).system().get_dof_map().add_coupling_functor(coupling_gf, to_mesh);
1063 42328 : cloneCouplingGhostingFunctor(coupling_gf, to_mesh);
1064 : }
1065 :
1066 : void
1067 27 : SubProblem::removeAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf)
1068 : {
1069 27 : EquationSystems & eq = es();
1070 27 : const auto n_sys = eq.n_systems();
1071 :
1072 : #ifndef NDEBUG
1073 : const DofMap & nl_dof_map = eq.get_system(0).get_dof_map();
1074 : const bool found_in_root_sys =
1075 : std::find(nl_dof_map.algebraic_ghosting_functors_begin(),
1076 : nl_dof_map.algebraic_ghosting_functors_end(),
1077 : &algebraic_gf) != nl_dof_map.algebraic_ghosting_functors_end();
1078 : const bool found_in_our_map =
1079 : _root_alg_gf_to_sys_clones.find(&algebraic_gf) != _root_alg_gf_to_sys_clones.end();
1080 : mooseAssert(found_in_root_sys == found_in_our_map,
1081 : "If the ghosting functor exists in the root DofMap, then we need to have a key for "
1082 : "it in our gf to clones map");
1083 : #endif
1084 :
1085 27 : eq.get_system(0).get_dof_map().remove_algebraic_ghosting_functor(algebraic_gf);
1086 :
1087 27 : auto it = _root_alg_gf_to_sys_clones.find(&algebraic_gf);
1088 27 : if (it == _root_alg_gf_to_sys_clones.end())
1089 27 : return;
1090 :
1091 0 : auto & clones_vec = it->second;
1092 : mooseAssert((n_sys - 1) == clones_vec.size(),
1093 : "The size of the gf clones vector doesn't match the number of systems minus one");
1094 0 : if (clones_vec.empty())
1095 : {
1096 : mooseAssert(n_sys == 1, "The clones vector should only be empty if there is only one system");
1097 0 : return;
1098 : }
1099 :
1100 0 : for (const auto i : make_range(n_sys))
1101 0 : eq.get_system(i + 1).get_dof_map().remove_algebraic_ghosting_functor(*clones_vec[i]);
1102 :
1103 0 : _root_alg_gf_to_sys_clones.erase(it->first);
1104 : }
1105 :
1106 : void
1107 27 : SubProblem::removeCouplingGhostingFunctor(GhostingFunctor & coupling_gf)
1108 : {
1109 27 : EquationSystems & eq = es();
1110 27 : const auto num_nl_sys = numNonlinearSystems();
1111 27 : if (!num_nl_sys)
1112 27 : return;
1113 :
1114 : #ifndef NDEBUG
1115 : const DofMap & nl_dof_map = eq.get_system(0).get_dof_map();
1116 : const bool found_in_root_sys = std::find(nl_dof_map.coupling_functors_begin(),
1117 : nl_dof_map.coupling_functors_end(),
1118 : &coupling_gf) != nl_dof_map.coupling_functors_end();
1119 : const bool found_in_our_map =
1120 : _root_coupling_gf_to_sys_clones.find(&coupling_gf) != _root_coupling_gf_to_sys_clones.end();
1121 : mooseAssert(found_in_root_sys == found_in_our_map,
1122 : "If the ghosting functor exists in the root DofMap, then we need to have a key for "
1123 : "it in our gf to clones map");
1124 : #endif
1125 :
1126 27 : eq.get_system(0).get_dof_map().remove_coupling_functor(coupling_gf);
1127 :
1128 27 : auto it = _root_coupling_gf_to_sys_clones.find(&coupling_gf);
1129 27 : if (it == _root_coupling_gf_to_sys_clones.end())
1130 0 : return;
1131 :
1132 27 : auto & clones_vec = it->second;
1133 : mooseAssert((num_nl_sys - 1) == clones_vec.size(),
1134 : "The size of the gf clones vector doesn't match the number of systems minus one");
1135 27 : if (clones_vec.empty())
1136 : {
1137 : mooseAssert(num_nl_sys == 1,
1138 : "The clones vector should only be empty if there is only one nonlinear system");
1139 27 : return;
1140 : }
1141 :
1142 0 : for (const auto i : make_range(num_nl_sys))
1143 0 : eq.get_system(i + 1).get_dof_map().remove_coupling_functor(*clones_vec[i]);
1144 :
1145 0 : _root_coupling_gf_to_sys_clones.erase(it->first);
1146 : }
1147 :
1148 : void
1149 61617 : SubProblem::automaticScaling(bool automatic_scaling)
1150 : {
1151 122359 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1152 60742 : systemBaseNonlinear(nl_sys_num).automaticScaling(automatic_scaling);
1153 61617 : }
1154 :
1155 : bool
1156 13780 : SubProblem::automaticScaling() const
1157 : {
1158 : // Currently going to assume that we are applying or not applying automatic scaling consistently
1159 : // across nonlinear systems
1160 13780 : return systemBaseNonlinear(0).automaticScaling();
1161 : }
1162 :
1163 : void
1164 352 : SubProblem::hasScalingVector(const unsigned int nl_sys_num)
1165 : {
1166 764 : for (const THREAD_ID tid : make_range(libMesh::n_threads()))
1167 412 : assembly(tid, nl_sys_num).hasScalingVector();
1168 352 : }
1169 :
1170 : void
1171 346137 : SubProblem::clearAllDofIndices()
1172 : {
1173 704104 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1174 357967 : systemBaseNonlinear(nl_sys_num).clearAllDofIndices();
1175 346137 : systemBaseAuxiliary().clearAllDofIndices();
1176 346137 : }
1177 :
1178 : void
1179 289789 : SubProblem::timestepSetup()
1180 : {
1181 607509 : for (auto & map : _pbblf_functors)
1182 327336 : for (auto & pr : map)
1183 9616 : pr.second->timestepSetup();
1184 289789 : }
1185 :
1186 : void
1187 1869251 : SubProblem::customSetup(const ExecFlagType & exec_type)
1188 : {
1189 3920481 : for (auto & map : _pbblf_functors)
1190 2119343 : for (auto & pr : map)
1191 68113 : pr.second->customSetup(exec_type);
1192 1869251 : }
1193 :
1194 : void
1195 3170529 : SubProblem::residualSetup()
1196 : {
1197 6648525 : for (auto & map : _pbblf_functors)
1198 3569597 : for (auto & pr : map)
1199 91601 : pr.second->residualSetup();
1200 3170529 : }
1201 :
1202 : void
1203 498165 : SubProblem::jacobianSetup()
1204 : {
1205 1046382 : for (auto & map : _pbblf_functors)
1206 562709 : for (auto & pr : map)
1207 14492 : pr.second->jacobianSetup();
1208 498165 : }
1209 :
1210 : void
1211 57568 : SubProblem::initialSetup()
1212 : {
1213 57568 : if (_output_functors)
1214 : {
1215 34 : showFunctors();
1216 34 : showFunctorRequestors();
1217 : }
1218 :
1219 120844 : for (const auto & functors : _functors)
1220 348903 : for (const auto & [functor_wrapper_name, functor_wrapper] : functors)
1221 : {
1222 285627 : const auto & [true_functor_type, non_ad_functor, ad_functor] = functor_wrapper;
1223 : mooseAssert(non_ad_functor->wrapsNull() == ad_functor->wrapsNull(), "These must agree");
1224 285627 : const auto functor_name = removeSubstring(functor_wrapper_name, "wraps_");
1225 285627 : if (non_ad_functor->wrapsNull())
1226 0 : mooseError(
1227 : "No functor ever provided with name '",
1228 : functor_name,
1229 : "', which was requested by '",
1230 0 : MooseUtils::join(libmesh_map_find(_functor_to_requestors, functor_wrapper_name), ","),
1231 : "'.");
1232 455883 : if (true_functor_type == TrueFunctorIs::NONAD ? non_ad_functor->ownsWrappedFunctor()
1233 170256 : : ad_functor->ownsWrappedFunctor())
1234 0 : mooseError("Functor envelopes should not own the functors they wrap, but '",
1235 : functor_name,
1236 : "' is owned by the wrapper. Please open a MOOSE issue for help resolving this.");
1237 285627 : }
1238 57568 : }
1239 :
1240 : void
1241 34 : SubProblem::showFunctors() const
1242 : {
1243 34 : _console << "[DBG] Wrapped functors found in Subproblem" << std::endl;
1244 34 : std::string functor_names = "[DBG] ";
1245 266 : for (const auto & functor_pair : _functors[0])
1246 232 : functor_names += std::regex_replace(functor_pair.first, std::regex("wraps_"), "") + " ";
1247 34 : if (functor_names.size())
1248 34 : functor_names.pop_back();
1249 34 : _console << functor_names << std::endl;
1250 34 : }
1251 :
1252 : void
1253 34 : SubProblem::showFunctorRequestors() const
1254 : {
1255 122 : for (const auto & [functor, requestors] : _functor_to_requestors)
1256 : {
1257 88 : _console << "[DBG] Requestors for wrapped functor "
1258 88 : << std::regex_replace(functor, std::regex("wraps_"), "") << std::endl;
1259 88 : _console << "[DBG] " << MooseUtils::join(requestors, " ") << std::endl;
1260 : }
1261 34 : }
1262 :
1263 : bool
1264 524 : SubProblem::hasFunctor(const std::string & name, const THREAD_ID tid) const
1265 : {
1266 : mooseAssert(tid < _functors.size(), "Too large a thread ID");
1267 524 : auto & functors = _functors[tid];
1268 524 : return (functors.find("wraps_" + name) != functors.end());
1269 : }
1270 :
1271 : Moose::CoordinateSystemType
1272 425951918 : SubProblem::getCoordSystem(SubdomainID sid) const
1273 : {
1274 425951918 : return mesh().getCoordSystem(sid);
1275 : }
1276 :
1277 : void
1278 23545598 : SubProblem::reinitFVFace(const THREAD_ID tid, const FaceInfo & fi)
1279 : {
1280 48061804 : for (const auto nl : make_range(numNonlinearSystems()))
1281 24516206 : assembly(tid, nl).reinitFVFace(fi);
1282 23545598 : }
1283 :
1284 : void
1285 338318018 : SubProblem::cacheResidual(const THREAD_ID tid)
1286 : {
1287 338318018 : assembly(tid, currentNlSysNum())
1288 338318018 : .cacheResidual(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1289 338318018 : }
1290 :
1291 : void
1292 35615312 : SubProblem::cacheResidualNeighbor(const THREAD_ID tid)
1293 : {
1294 35615312 : assembly(tid, currentNlSysNum())
1295 35615312 : .cacheResidualNeighbor(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1296 35615312 : }
1297 :
1298 : void
1299 53000396 : SubProblem::addCachedResidual(const THREAD_ID tid)
1300 : {
1301 53000396 : assembly(tid, currentNlSysNum())
1302 53000396 : .addCachedResiduals(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1303 53000396 : }
1304 :
1305 : void
1306 51041992 : SubProblem::cacheJacobian(const THREAD_ID tid)
1307 : {
1308 51041992 : assembly(tid, currentNlSysNum()).cacheJacobian(Assembly::GlobalDataKey{});
1309 51041992 : if (hasNonlocalCoupling())
1310 5166 : assembly(tid, currentNlSysNum()).cacheJacobianNonlocal(Assembly::GlobalDataKey{});
1311 51041992 : }
1312 :
1313 : void
1314 9290 : SubProblem::cacheJacobianNeighbor(const THREAD_ID tid)
1315 : {
1316 9290 : assembly(tid, currentNlSysNum()).cacheJacobianNeighbor(Assembly::GlobalDataKey{});
1317 9290 : }
1318 :
1319 : void
1320 3819642 : SubProblem::addCachedJacobian(const THREAD_ID tid)
1321 : {
1322 3819642 : assembly(tid, currentNlSysNum()).addCachedJacobian(Assembly::GlobalDataKey{});
1323 3819638 : }
1324 :
1325 : void
1326 216 : SubProblem::preparePRefinement()
1327 : {
1328 216 : std::unordered_set<FEFamily> disable_families;
1329 612 : for (const auto & [family, flag] : _family_for_p_refinement)
1330 396 : if (flag)
1331 180 : disable_families.insert(family);
1332 :
1333 450 : for (const auto tid : make_range(libMesh::n_threads()))
1334 468 : for (const auto s : make_range(numNonlinearSystems()))
1335 234 : assembly(tid, s).havePRefinement(disable_families);
1336 :
1337 216 : auto & eq = es();
1338 396 : for (const auto family : disable_families)
1339 540 : for (const auto i : make_range(eq.n_systems()))
1340 : {
1341 360 : auto & system = eq.get_system(i);
1342 360 : auto & dof_map = system.get_dof_map();
1343 864 : for (const auto vg : make_range(system.n_variable_groups()))
1344 : {
1345 504 : const auto & var_group = system.variable_group(vg);
1346 504 : if (var_group.type().family == family)
1347 180 : dof_map.should_p_refine(vg, false);
1348 : }
1349 : }
1350 :
1351 216 : _have_p_refinement = true;
1352 216 : }
1353 :
1354 : bool
1355 424 : SubProblem::doingPRefinement() const
1356 : {
1357 424 : return mesh().doingPRefinement();
1358 : }
1359 :
1360 : void
1361 146529 : SubProblem::markFamilyPRefinement(const InputParameters & params)
1362 : {
1363 146529 : auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
1364 146529 : bool flag = _default_families_without_p_refinement.count(family);
1365 146529 : if (params.isParamValid("disable_p_refinement"))
1366 132 : flag = params.get<bool>("disable_p_refinement");
1367 :
1368 146529 : auto [it, inserted] = _family_for_p_refinement.emplace(family, flag);
1369 146529 : if (!inserted && flag != it->second)
1370 0 : mooseError("'disable_p_refinement' not set consistently for variables in ", family);
1371 146529 : }
1372 :
1373 : void
1374 139290 : SubProblem::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
1375 : {
1376 278580 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1377 139290 : assembly(tid, nl_sys_num).setCurrentLowerDElem(lower_d_elem);
1378 139290 : }
1379 :
1380 : template MooseVariableFEBase &
1381 : SubProblem::getVariableHelper(const THREAD_ID tid,
1382 : const std::string & var_name,
1383 : Moose::VarKindType expected_var_type,
1384 : Moose::VarFieldType expected_var_field_type,
1385 : const std::vector<std::shared_ptr<SolverSystem>> & nls,
1386 : const SystemBase & aux) const;
1387 : template MooseVariableFEBase &
1388 : SubProblem::getVariableHelper(const THREAD_ID tid,
1389 : const std::string & var_name,
1390 : Moose::VarKindType expected_var_type,
1391 : Moose::VarFieldType expected_var_field_type,
1392 : const std::vector<std::unique_ptr<DisplacedSystem>> & nls,
1393 : const SystemBase & aux) const;
|