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 357765 : SubProblem::validParams()
37 : {
38 357765 : InputParameters params = Problem::validParams();
39 :
40 1073295 : params.addParam<bool>(
41 : "default_ghosting",
42 715530 : false,
43 : "Whether or not to use libMesh's default amount of algebraic and geometric ghosting");
44 :
45 357765 : params.addParamNamesToGroup("default_ghosting", "Advanced");
46 :
47 357765 : 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 64731 : SubProblem::SubProblem(const InputParameters & parameters)
61 : : Problem(parameters),
62 64731 : _factory(_app.getFactory()),
63 64731 : _default_ghosting(getParam<bool>("default_ghosting")),
64 64731 : _currently_computing_jacobian(false),
65 64731 : _currently_computing_residual_and_jacobian(false),
66 64731 : _computing_nonlinear_residual(false),
67 64731 : _currently_computing_residual(false),
68 64731 : _safe_access_tagged_matrices(false),
69 64731 : _safe_access_tagged_vectors(false),
70 64731 : _have_ad_objects(false),
71 64731 : _output_functors(false),
72 64731 : _typed_vector_tags(2),
73 258924 : _have_p_refinement(false)
74 : {
75 64731 : unsigned int n_threads = libMesh::n_threads();
76 64731 : _active_elemental_moose_variables.resize(n_threads);
77 64731 : _has_active_elemental_moose_variables.resize(n_threads);
78 :
79 64731 : _active_fe_var_coupleable_matrix_tags.resize(n_threads);
80 64731 : _active_fe_var_coupleable_vector_tags.resize(n_threads);
81 64731 : _active_sc_var_coupleable_matrix_tags.resize(n_threads);
82 64731 : _active_sc_var_coupleable_vector_tags.resize(n_threads);
83 :
84 64731 : _functors.resize(n_threads);
85 64731 : _pbblf_functors.resize(n_threads);
86 64731 : _functor_to_request_info.resize(n_threads);
87 64731 : }
88 :
89 60383 : SubProblem::~SubProblem() {}
90 :
91 : TagID
92 483889 : SubProblem::addVectorTag(const TagName & tag_name,
93 : const Moose::VectorTagType type /* = Moose::VECTOR_TAG_RESIDUAL */)
94 : {
95 483889 : if (type == Moose::VECTOR_TAG_ANY)
96 0 : mooseError("Vector tag type cannot be VECTOR_TAG_ANY");
97 :
98 483889 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
99 :
100 : // First, see if the tag exists already
101 2145731 : for (const auto & vector_tag : _vector_tags)
102 : {
103 : mooseAssert(_vector_tags[vector_tag._id] == vector_tag, "Vector tags index mismatch");
104 1755586 : if (vector_tag._name == tag_name_upper)
105 : {
106 93744 : 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 93744 : return vector_tag._id;
116 : }
117 : }
118 :
119 : // Doesn't exist - create it
120 390145 : const TagID new_tag_id = _vector_tags.size();
121 390145 : 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 390145 : _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 390145 : _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 390145 : _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 390145 : verifyVectorTags();
131 :
132 390145 : return new_tag_id;
133 483889 : }
134 :
135 : bool
136 326695 : SubProblem::vectorTagExists(const TagName & tag_name) const
137 : {
138 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
139 :
140 326695 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
141 3018729 : for (const auto & vector_tag : _vector_tags)
142 2706627 : if (vector_tag._name == tag_name_upper)
143 14593 : return true;
144 :
145 312102 : return false;
146 326695 : }
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 9466836 : SubProblem::vectorTagNotZeroed(const TagID tag) const
156 : {
157 9466836 : return _not_zeroed_tagged_vectors.count(tag);
158 : }
159 :
160 : const VectorTag &
161 933508989 : SubProblem::getVectorTag(const TagID tag_id) const
162 : {
163 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
164 :
165 933508989 : if (!vectorTagExists(tag_id))
166 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
167 :
168 933508989 : return _vector_tags[tag_id];
169 : }
170 :
171 : std::vector<VectorTag>
172 6573130 : SubProblem::getVectorTags(const std::set<TagID> & tag_ids) const
173 : {
174 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
175 :
176 6573130 : std::vector<VectorTag> tags;
177 6573130 : tags.reserve(tag_ids.size());
178 25524013 : for (const auto & tag_id : tag_ids)
179 18950883 : tags.push_back(getVectorTag(tag_id));
180 6573130 : return tags;
181 0 : }
182 :
183 : const std::vector<VectorTag> &
184 11442069 : SubProblem::getVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
185 : {
186 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
187 :
188 11442069 : if (type == Moose::VECTOR_TAG_ANY)
189 550989 : return _vector_tags;
190 : else
191 10891080 : return _typed_vector_tags[type];
192 : }
193 :
194 : unsigned int
195 8080647 : SubProblem::numVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
196 : {
197 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
198 :
199 8080647 : return getVectorTags(type).size();
200 : }
201 :
202 : TagID
203 6719334 : SubProblem::getVectorTagID(const TagName & tag_name) const
204 : {
205 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
206 :
207 6719334 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
208 6719334 : const auto search = _vector_tags_name_map.find(tag_name_upper);
209 6719334 : if (search != _vector_tags_name_map.end())
210 13438636 : 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 6719318 : }
219 :
220 : TagName
221 162614 : SubProblem::vectorTagName(const TagID tag_id) const
222 : {
223 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
224 162614 : if (!vectorTagExists(tag_id))
225 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
226 :
227 162614 : return _vector_tags[tag_id]._name;
228 : }
229 :
230 : Moose::VectorTagType
231 2507929963 : SubProblem::vectorTagType(const TagID tag_id) const
232 : {
233 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
234 2507929963 : if (!vectorTagExists(tag_id))
235 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
236 :
237 2507929963 : return _vector_tags[tag_id]._type;
238 : }
239 :
240 : bool
241 390145 : SubProblem::verifyVectorTags() const
242 : {
243 1971120 : for (TagID tag_id = 0; tag_id < _vector_tags.size(); ++tag_id)
244 : {
245 1580975 : const auto & vector_tag = _vector_tags[tag_id];
246 :
247 1580975 : if (vector_tag._id != tag_id)
248 0 : mooseError("Vector tag ", vector_tag._id, " id mismatch in _vector_tags");
249 1580975 : if (vector_tag._type == Moose::VECTOR_TAG_ANY)
250 0 : mooseError("Vector tag '", vector_tag._name, "' has type VECTOR_TAG_ANY");
251 :
252 1580975 : const auto search = _vector_tags_name_map.find(vector_tag._name);
253 1580975 : if (search == _vector_tags_name_map.end())
254 0 : mooseError("Vector tag ", vector_tag._id, " is not in _vector_tags_name_map");
255 1580975 : else if (search->second != tag_id)
256 0 : mooseError("Vector tag ", vector_tag._id, " has incorrect id in _vector_tags_name_map");
257 :
258 1580975 : unsigned int found_in_type = 0;
259 6530176 : for (TagTypeID tag_type_id = 0; tag_type_id < _typed_vector_tags[vector_tag._type].size();
260 : ++tag_type_id)
261 : {
262 4949201 : const auto & vector_tag_type = _typed_vector_tags[vector_tag._type][tag_type_id];
263 4949201 : if (vector_tag_type == vector_tag)
264 : {
265 1580975 : ++found_in_type;
266 1580975 : 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 1580975 : if (found_in_type == 0)
272 0 : mooseError("Vector tag ", tag_id, " not found in _typed_vector_tags");
273 1580975 : if (found_in_type > 1)
274 0 : mooseError("Vector tag ", tag_id, " found multiple times in _typed_vector_tags");
275 : }
276 :
277 390145 : unsigned int num_typed_vector_tags = 0;
278 1170435 : for (const auto & typed_vector_tags : _typed_vector_tags)
279 780290 : num_typed_vector_tags += typed_vector_tags.size();
280 390145 : if (num_typed_vector_tags != _vector_tags.size())
281 0 : mooseError("Size mismatch between _vector_tags and _typed_vector_tags");
282 390145 : if (_vector_tags_name_map.size() != _vector_tags.size())
283 0 : mooseError("Size mismatch between _vector_tags and _vector_tags_name_map");
284 :
285 390145 : return true;
286 : }
287 :
288 : void
289 3252629 : SubProblem::selectVectorTagsFromSystem(const SystemBase & system,
290 : const std::vector<VectorTag> & input_vector_tags,
291 : std::set<TagID> & selected_tags)
292 : {
293 3252629 : selected_tags.clear();
294 12671440 : for (const auto & vector_tag : input_vector_tags)
295 9418811 : if (system.hasVector(vector_tag._id))
296 9418189 : selected_tags.insert(vector_tag._id);
297 3252629 : }
298 :
299 : void
300 5366 : SubProblem::selectMatrixTagsFromSystem(const SystemBase & system,
301 : const std::map<TagName, TagID> & input_matrix_tags,
302 : std::set<TagID> & selected_tags)
303 : {
304 5366 : selected_tags.clear();
305 10869 : for (const auto & matrix_tag_pair : input_matrix_tags)
306 5503 : if (system.hasMatrix(matrix_tag_pair.second))
307 5390 : selected_tags.insert(matrix_tag_pair.second);
308 5366 : }
309 :
310 : TagID
311 126332 : SubProblem::addMatrixTag(TagName tag_name)
312 : {
313 126332 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
314 126332 : auto existing_tag = _matrix_tag_name_to_tag_id.find(tag_name_upper);
315 126332 : if (existing_tag == _matrix_tag_name_to_tag_id.end())
316 : {
317 125815 : auto tag_id = _matrix_tag_name_to_tag_id.size();
318 :
319 125815 : _matrix_tag_name_to_tag_id[tag_name_upper] = tag_id;
320 :
321 125815 : _matrix_tag_id_to_tag_name[tag_id] = tag_name_upper;
322 : }
323 :
324 252664 : return _matrix_tag_name_to_tag_id.at(tag_name_upper);
325 126332 : }
326 :
327 : bool
328 297957 : SubProblem::matrixTagExists(const TagName & tag_name) const
329 : {
330 297957 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
331 :
332 595914 : return _matrix_tag_name_to_tag_id.find(tag_name_upper) != _matrix_tag_name_to_tag_id.end();
333 297957 : }
334 :
335 : bool
336 1636908 : SubProblem::matrixTagExists(TagID tag_id) const
337 : {
338 1636908 : return _matrix_tag_id_to_tag_name.find(tag_id) != _matrix_tag_id_to_tag_name.end();
339 : }
340 :
341 : TagID
342 296547 : SubProblem::getMatrixTagID(const TagName & tag_name) const
343 : {
344 296547 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
345 :
346 296547 : 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 593086 : return _matrix_tag_name_to_tag_id.at(tag_name_upper);
354 296543 : }
355 :
356 : TagName
357 348 : SubProblem::matrixTagName(TagID tag)
358 : {
359 348 : return _matrix_tag_id_to_tag_name[tag];
360 : }
361 :
362 : void
363 635077 : SubProblem::setActiveFEVariableCoupleableMatrixTags(std::set<TagID> & mtags, const THREAD_ID tid)
364 : {
365 635077 : _active_fe_var_coupleable_matrix_tags[tid] = mtags;
366 635077 : }
367 :
368 : void
369 7415273 : SubProblem::setActiveFEVariableCoupleableVectorTags(std::set<TagID> & vtags, const THREAD_ID tid)
370 : {
371 7415273 : _active_fe_var_coupleable_vector_tags[tid] = vtags;
372 14962702 : for (const auto sys_num : make_range(numSolverSystems()))
373 7547429 : systemBaseSolver(sys_num).setActiveVariableCoupleableVectorTags(vtags, tid);
374 7415273 : systemBaseAuxiliary().setActiveVariableCoupleableVectorTags(vtags, tid);
375 7415273 : }
376 :
377 : void
378 296657 : SubProblem::clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
379 : {
380 296657 : _active_fe_var_coupleable_vector_tags[tid].clear();
381 296657 : }
382 :
383 : void
384 296657 : SubProblem::clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
385 : {
386 296657 : _active_fe_var_coupleable_matrix_tags[tid].clear();
387 296657 : }
388 :
389 : const std::set<TagID> &
390 1941354761 : SubProblem::getActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid) const
391 : {
392 1941354761 : return _active_fe_var_coupleable_matrix_tags[tid];
393 : }
394 :
395 : const std::set<TagID> &
396 334 : SubProblem::getActiveFEVariableCoupleableVectorTags(const THREAD_ID tid) const
397 : {
398 334 : return _active_fe_var_coupleable_vector_tags[tid];
399 : }
400 :
401 : void
402 56031 : SubProblem::setActiveScalarVariableCoupleableMatrixTags(std::set<TagID> & mtags,
403 : const THREAD_ID tid)
404 : {
405 56031 : _active_sc_var_coupleable_matrix_tags[tid] = mtags;
406 56031 : }
407 :
408 : void
409 56031 : SubProblem::setActiveScalarVariableCoupleableVectorTags(std::set<TagID> & vtags,
410 : const THREAD_ID tid)
411 : {
412 56031 : _active_sc_var_coupleable_vector_tags[tid] = vtags;
413 112062 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
414 56031 : systemBaseNonlinear(nl_sys_num).setActiveScalarVariableCoupleableVectorTags(vtags, tid);
415 56031 : systemBaseAuxiliary().setActiveScalarVariableCoupleableVectorTags(vtags, tid);
416 56031 : }
417 :
418 : void
419 56031 : SubProblem::clearActiveScalarVariableCoupleableVectorTags(const THREAD_ID tid)
420 : {
421 56031 : _active_sc_var_coupleable_vector_tags[tid].clear();
422 56031 : }
423 :
424 : void
425 56031 : SubProblem::clearActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid)
426 : {
427 56031 : _active_sc_var_coupleable_matrix_tags[tid].clear();
428 56031 : }
429 :
430 : const std::set<TagID> &
431 573761 : SubProblem::getActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) const
432 : {
433 573761 : 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 11402727 : SubProblem::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
444 : const THREAD_ID tid)
445 : {
446 11402727 : if (!moose_vars.empty())
447 : {
448 11060248 : _has_active_elemental_moose_variables[tid] = 1;
449 11060248 : _active_elemental_moose_variables[tid] = moose_vars;
450 : }
451 11402727 : }
452 :
453 : const std::set<MooseVariableFEBase *> &
454 1274264875 : SubProblem::getActiveElementalMooseVariables(const THREAD_ID tid) const
455 : {
456 1274264875 : return _active_elemental_moose_variables[tid];
457 : }
458 :
459 : bool
460 1319349218 : SubProblem::hasActiveElementalMooseVariables(const THREAD_ID tid) const
461 : {
462 1319349218 : return _has_active_elemental_moose_variables[tid];
463 : }
464 :
465 : void
466 4850814 : SubProblem::clearActiveElementalMooseVariables(const THREAD_ID tid)
467 : {
468 4850814 : _has_active_elemental_moose_variables[tid] = 0;
469 4850814 : _active_elemental_moose_variables[tid].clear();
470 4850814 : }
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 360 : SubProblem::hasBlockMaterialProperty(SubdomainID bid, const std::string & prop_name)
512 : {
513 360 : auto it = _map_block_material_props.find(bid);
514 360 : if (it == _map_block_material_props.end())
515 0 : return false;
516 :
517 360 : if (it->second.count(prop_name) > 0)
518 270 : return true;
519 : else
520 90 : 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 67510 : SubProblem::storeSubdomainMatPropName(SubdomainID block_id, const std::string & name)
584 : {
585 67510 : _map_block_material_props[block_id].insert(name);
586 67510 : }
587 :
588 : void
589 63542 : SubProblem::storeBoundaryMatPropName(BoundaryID boundary_id, const std::string & name)
590 : {
591 63542 : _map_boundary_material_props[boundary_id].insert(name);
592 63542 : }
593 :
594 : void
595 9522 : SubProblem::storeSubdomainZeroMatProp(SubdomainID block_id, const MaterialPropertyName & name)
596 : {
597 9522 : _zero_block_material_props[block_id].insert(name);
598 9522 : }
599 :
600 : void
601 9522 : SubProblem::storeBoundaryZeroMatProp(BoundaryID boundary_id, const MaterialPropertyName & name)
602 : {
603 9522 : _zero_boundary_material_props[boundary_id].insert(name);
604 9522 : }
605 :
606 : void
607 45359 : SubProblem::storeSubdomainDelayedCheckMatProp(const std::string & requestor,
608 : SubdomainID block_id,
609 : const std::string & name)
610 : {
611 45359 : _map_block_material_props_check[block_id].insert(std::make_pair(requestor, name));
612 45359 : }
613 :
614 : void
615 6131 : SubProblem::storeBoundaryDelayedCheckMatProp(const std::string & requestor,
616 : BoundaryID boundary_id,
617 : const std::string & name)
618 : {
619 6131 : _map_boundary_material_props_check[boundary_id].insert(std::make_pair(requestor, name));
620 6131 : }
621 :
622 : void
623 60531 : SubProblem::checkBlockMatProps()
624 : {
625 : // Variable for storing all available blocks/boundaries from the mesh
626 60531 : std::set<SubdomainID> all_ids(mesh().meshSubdomains());
627 :
628 60531 : std::stringstream errors;
629 :
630 : // Loop through the properties to check
631 66542 : for (const auto & check_it : _map_block_material_props_check)
632 : {
633 : // The current id for the property being checked (BoundaryID || BlockID)
634 6011 : SubdomainID check_id = check_it.first;
635 :
636 6011 : std::set<SubdomainID> check_ids = {check_id};
637 :
638 : // Loop through all the block/boundary ids
639 12022 : for (const auto & id : check_ids)
640 : {
641 : // Loop through all the stored properties
642 49143 : 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 43238 : if (_map_block_material_props[id].count(prop_it.second) == 0 &&
648 43238 : _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 6011 : }
659 :
660 60531 : if (!errors.str().empty())
661 40 : mooseError(errors.str());
662 60491 : }
663 :
664 : void
665 60491 : SubProblem::checkBoundaryMatProps()
666 : {
667 : // Variable for storing the value for ANY_BOUNDARY_ID
668 60491 : BoundaryID any_id = Moose::ANY_BOUNDARY_ID;
669 :
670 : // Variable for storing all available blocks/boundaries from the mesh
671 60491 : std::set<BoundaryID> all_ids(mesh().getBoundaryIDs());
672 :
673 60491 : std::stringstream errors;
674 :
675 : // Loop through the properties to check
676 63082 : for (const auto & check_it : _map_boundary_material_props_check)
677 : {
678 : // The current id for the property being checked (BoundaryID || BlockID)
679 2591 : 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 2591 : std::set<BoundaryID> check_ids{check_id};
684 2591 : if (check_id == any_id)
685 0 : check_ids = all_ids;
686 :
687 : // Loop through all the block/boundary ids
688 5182 : for (const auto & id : check_ids)
689 : {
690 : // Loop through all the stored properties
691 8722 : 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 6131 : if (_map_boundary_material_props[id].count(prop_it.second) == 0 &&
697 4830 : _map_boundary_material_props[any_id].count(prop_it.second) == 0 &&
698 23238 : _zero_boundary_material_props[id].count(prop_it.second) == 0 &&
699 6146 : _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 2591 : }
710 :
711 60491 : if (!errors.str().empty())
712 12 : mooseError(errors.str());
713 60479 : }
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 64092 : SubProblem::markMatPropRequested(const std::string & prop_name)
725 : {
726 64092 : _material_property_requested.insert(prop_name);
727 64092 : }
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 49906 : SubProblem::addConsumedPropertyName(const MooseObjectName & obj_name, const std::string & prop_name)
737 : {
738 49906 : _consumed_material_properties[obj_name].insert(prop_name);
739 49906 : }
740 :
741 : const std::map<MooseObjectName, std::set<std::string>> &
742 218 : SubProblem::getConsumedPropertyMap() const
743 : {
744 218 : return _consumed_material_properties;
745 : }
746 :
747 : DiracKernelInfo &
748 999 : SubProblem::diracKernelInfo()
749 : {
750 999 : 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 144883499 : SubProblem::setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid)
790 : {
791 291067649 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
792 146184150 : assembly(tid, nl_sys_num).setCurrentBoundaryID(bid);
793 144883499 : }
794 :
795 : unsigned int
796 216 : SubProblem::getAxisymmetricRadialCoord() const
797 : {
798 216 : 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 18 : SubProblem::hasAuxiliaryVariable(const std::string & var_name) const
812 : {
813 18 : return systemBaseAuxiliary().hasVariable(var_name);
814 : }
815 :
816 : template <typename T>
817 : MooseVariableFEBase &
818 4738196 : 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 4738196 : MooseVariableFEBase * var = nullptr;
827 :
828 4738196 : const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
829 :
830 : // First check that the variable is found on the expected system.
831 4738196 : if (expected_var_type == Moose::VarKindType::VAR_ANY)
832 : {
833 2571579 : if (var_in_sys)
834 1166541 : var = &(systems[sys_num]->getVariable(tid, var_name));
835 1405038 : else if (aux.hasVariable(var_name))
836 1405038 : var = &(aux.getVariable(tid, var_name));
837 : else
838 0 : mooseError("Unknown variable " + var_name);
839 : }
840 2358363 : else if (expected_var_type == Moose::VarKindType::VAR_SOLVER && var_in_sys &&
841 191746 : systems[sys_num]->hasVariable(var_name))
842 191746 : var = &(systems[sys_num]->getVariable(tid, var_name));
843 1974871 : else if (expected_var_type == Moose::VarKindType::VAR_AUXILIARY && aux.hasVariable(var_name))
844 1974871 : 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 6967613 : if ((expected_var_field_type == Moose::VarFieldType::VAR_FIELD_ANY) ||
860 2229417 : (expected_var_field_type == var->fieldType()))
861 4738188 : 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 306709 : 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 613418 : 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 306709 : assembly(tid, nl_sys_num).reinitElemFaceRef(elem, side, tolerance, pts, weights);
897 :
898 306709 : auto & nl = systemBaseNonlinear(nl_sys_num);
899 :
900 : // Actually get the dof indices in the moose variables
901 306709 : nl.prepare(tid);
902 :
903 : // Let's finally compute our variable values!
904 306709 : nl.reinitElemFace(elem, side, tid);
905 : }
906 :
907 : // do same for aux as for nl
908 306709 : systemBaseAuxiliary().prepare(tid);
909 306709 : 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 306709 : auto & current_assembly = assembly(tid, currentNlSysNum());
914 306709 : if (currentlyComputingJacobian() || currentlyComputingResidualAndJacobian())
915 101151 : current_assembly.prepareJacobianBlock();
916 306709 : if (!currentlyComputingJacobian())
917 205558 : current_assembly.prepareResidual();
918 306709 : }
919 :
920 : void
921 306709 : 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 613418 : 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 306709 : assembly(tid, nl_sys_num)
936 306709 : .reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights);
937 :
938 306709 : auto & nl = systemBaseNonlinear(nl_sys_num);
939 :
940 : // Actually get the dof indices in the moose variables
941 306709 : nl.prepareNeighbor(tid);
942 :
943 : // Let's finally compute our variable values!
944 306709 : nl.reinitNeighborFace(neighbor_elem, neighbor_side, tid);
945 : }
946 :
947 : // do same for aux as for nl
948 306709 : systemBaseAuxiliary().prepareNeighbor(tid);
949 306709 : 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 306709 : assembly(tid, currentNlSysNum()).prepareNeighbor();
954 306709 : }
955 :
956 : void
957 325712 : 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 651424 : 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 325712 : assembly(tid, nl_sys_num).reinitLowerDElem(elem, pts, weights);
967 :
968 325712 : auto & nl = systemBaseNonlinear(nl_sys_num);
969 :
970 : // Actually get the dof indices in the moose variables
971 325712 : 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 325712 : assembly(tid, nl_sys_num).prepareLowerD();
976 :
977 : // Let's finally compute our variable values!
978 325712 : nl.reinitLowerD(tid);
979 : }
980 :
981 : // do same for aux as for nl
982 325712 : systemBaseAuxiliary().prepareLowerD(tid);
983 325712 : systemBaseAuxiliary().reinitLowerD(tid);
984 325712 : }
985 :
986 : void
987 284081 : SubProblem::reinitNeighborLowerDElem(const Elem * elem, const THREAD_ID tid)
988 : {
989 568162 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
990 284081 : assembly(tid, nl_sys_num).reinitNeighborLowerDElem(elem);
991 284081 : }
992 :
993 : void
994 568162 : SubProblem::reinitMortarElem(const Elem * elem, const THREAD_ID tid)
995 : {
996 1136324 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
997 568162 : assembly(tid, nl_sys_num).reinitMortarElem(elem);
998 568162 : }
999 :
1000 : void
1001 33595 : SubProblem::cloneAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
1002 : {
1003 33595 : EquationSystems & eq = es();
1004 33595 : const auto n_sys = eq.n_systems();
1005 :
1006 67190 : auto pr = _root_alg_gf_to_sys_clones.emplace(
1007 33595 : &algebraic_gf, std::vector<std::shared_ptr<GhostingFunctor>>(n_sys - 1));
1008 : mooseAssert(pr.second, "We are adding a duplicate algebraic ghosting functor");
1009 33595 : auto & clones_vec = pr.first->second;
1010 :
1011 67378 : for (MooseIndex(n_sys) i = 1; i < n_sys; ++i)
1012 : {
1013 33783 : DofMap & dof_map = eq.get_system(i).get_dof_map();
1014 33783 : std::shared_ptr<GhostingFunctor> clone_alg_gf = algebraic_gf.clone();
1015 67566 : std::dynamic_pointer_cast<RelationshipManager>(clone_alg_gf)
1016 33783 : ->init(mesh(), *algebraic_gf.get_mesh(), &dof_map);
1017 33783 : dof_map.add_algebraic_ghosting_functor(clone_alg_gf, to_mesh);
1018 33783 : clones_vec[i - 1] = clone_alg_gf;
1019 33783 : }
1020 33595 : }
1021 :
1022 : void
1023 33595 : SubProblem::addAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
1024 : {
1025 33595 : EquationSystems & eq = es();
1026 33595 : const auto n_sys = eq.n_systems();
1027 33595 : if (!n_sys)
1028 0 : return;
1029 :
1030 33595 : eq.get_system(0).get_dof_map().add_algebraic_ghosting_functor(algebraic_gf, to_mesh);
1031 33595 : cloneAlgebraicGhostingFunctor(algebraic_gf, to_mesh);
1032 : }
1033 :
1034 : void
1035 45486 : SubProblem::cloneCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
1036 : {
1037 45486 : const std::size_t num_nl_sys = numNonlinearSystems();
1038 :
1039 90972 : auto pr = _root_coupling_gf_to_sys_clones.emplace(
1040 45486 : &coupling_gf, std::vector<std::shared_ptr<GhostingFunctor>>(num_nl_sys - 1));
1041 : mooseAssert(pr.second, "We are adding a duplicate coupling functor");
1042 45486 : auto & clones_vec = pr.first->second;
1043 :
1044 45685 : for (const auto i : make_range(std::size_t(1), num_nl_sys))
1045 : {
1046 199 : DofMap & dof_map = systemBaseNonlinear(i).system().get_dof_map();
1047 199 : std::shared_ptr<GhostingFunctor> clone_coupling_gf = coupling_gf.clone();
1048 398 : std::dynamic_pointer_cast<RelationshipManager>(clone_coupling_gf)
1049 199 : ->init(mesh(), *coupling_gf.get_mesh(), &dof_map);
1050 199 : dof_map.add_coupling_functor(clone_coupling_gf, to_mesh);
1051 199 : clones_vec[i - 1] = clone_coupling_gf;
1052 199 : }
1053 45486 : }
1054 :
1055 : void
1056 46750 : SubProblem::addCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
1057 : {
1058 46750 : const auto num_nl_sys = numNonlinearSystems();
1059 46750 : if (!num_nl_sys)
1060 1264 : return;
1061 :
1062 45486 : systemBaseNonlinear(0).system().get_dof_map().add_coupling_functor(coupling_gf, to_mesh);
1063 45486 : cloneCouplingGhostingFunctor(coupling_gf, to_mesh);
1064 : }
1065 :
1066 : void
1067 30 : SubProblem::removeAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf)
1068 : {
1069 30 : EquationSystems & eq = es();
1070 30 : const auto n_sys = eq.n_systems();
1071 30 : DofMap & nl_dof_map = eq.get_system(0).get_dof_map();
1072 :
1073 : const bool found_in_root_sys =
1074 30 : std::find(nl_dof_map.algebraic_ghosting_functors_begin(),
1075 : nl_dof_map.algebraic_ghosting_functors_end(),
1076 60 : &algebraic_gf) != nl_dof_map.algebraic_ghosting_functors_end();
1077 :
1078 : #ifndef NDEBUG
1079 : const bool found_in_our_map =
1080 : _root_alg_gf_to_sys_clones.find(&algebraic_gf) != _root_alg_gf_to_sys_clones.end();
1081 : mooseAssert(found_in_root_sys == found_in_our_map,
1082 : "If the ghosting functor exists in the root DofMap, then we need to have a key for "
1083 : "it in our gf to clones map");
1084 : #endif
1085 :
1086 30 : if (found_in_root_sys) // libMesh yells if we try to remove
1087 : // something that's not there
1088 0 : nl_dof_map.remove_algebraic_ghosting_functor(algebraic_gf);
1089 :
1090 30 : auto it = _root_alg_gf_to_sys_clones.find(&algebraic_gf);
1091 30 : if (it == _root_alg_gf_to_sys_clones.end())
1092 30 : return;
1093 :
1094 0 : auto & clones_vec = it->second;
1095 : mooseAssert((n_sys - 1) == clones_vec.size(),
1096 : "The size of the gf clones vector doesn't match the number of systems minus one");
1097 0 : if (clones_vec.empty())
1098 : {
1099 : mooseAssert(n_sys == 1, "The clones vector should only be empty if there is only one system");
1100 0 : return;
1101 : }
1102 :
1103 0 : for (const auto i : make_range(n_sys))
1104 0 : eq.get_system(i + 1).get_dof_map().remove_algebraic_ghosting_functor(*clones_vec[i]);
1105 :
1106 0 : _root_alg_gf_to_sys_clones.erase(it->first);
1107 : }
1108 :
1109 : void
1110 30 : SubProblem::removeCouplingGhostingFunctor(GhostingFunctor & coupling_gf)
1111 : {
1112 30 : EquationSystems & eq = es();
1113 30 : const auto num_nl_sys = numNonlinearSystems();
1114 30 : if (!num_nl_sys)
1115 30 : return;
1116 :
1117 30 : DofMap & nl_dof_map = eq.get_system(0).get_dof_map();
1118 30 : const bool found_in_root_sys = std::find(nl_dof_map.coupling_functors_begin(),
1119 : nl_dof_map.coupling_functors_end(),
1120 60 : &coupling_gf) != nl_dof_map.coupling_functors_end();
1121 :
1122 : #ifndef NDEBUG
1123 : const bool found_in_our_map =
1124 : _root_coupling_gf_to_sys_clones.find(&coupling_gf) != _root_coupling_gf_to_sys_clones.end();
1125 : mooseAssert(found_in_root_sys == found_in_our_map,
1126 : "If the ghosting functor exists in the root DofMap, then we need to have a key for "
1127 : "it in our gf to clones map");
1128 : #endif
1129 :
1130 30 : if (found_in_root_sys) // libMesh yells if we try to remove
1131 : // something that's not there
1132 30 : nl_dof_map.remove_coupling_functor(coupling_gf);
1133 :
1134 30 : auto it = _root_coupling_gf_to_sys_clones.find(&coupling_gf);
1135 30 : if (it == _root_coupling_gf_to_sys_clones.end())
1136 0 : return;
1137 :
1138 30 : auto & clones_vec = it->second;
1139 : mooseAssert((num_nl_sys - 1) == clones_vec.size(),
1140 : "The size of the gf clones vector doesn't match the number of systems minus one");
1141 30 : if (clones_vec.empty())
1142 : {
1143 : mooseAssert(num_nl_sys == 1,
1144 : "The clones vector should only be empty if there is only one nonlinear system");
1145 30 : return;
1146 : }
1147 :
1148 0 : for (const auto i : make_range(num_nl_sys))
1149 0 : eq.get_system(i + 1).get_dof_map().remove_coupling_functor(*clones_vec[i]);
1150 :
1151 0 : _root_coupling_gf_to_sys_clones.erase(it->first);
1152 : }
1153 :
1154 : void
1155 66379 : SubProblem::automaticScaling(bool automatic_scaling)
1156 : {
1157 131717 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1158 65338 : systemBaseNonlinear(nl_sys_num).automaticScaling(automatic_scaling);
1159 66379 : }
1160 :
1161 : bool
1162 14652 : SubProblem::automaticScaling() const
1163 : {
1164 : // Currently going to assume that we are applying or not applying automatic scaling consistently
1165 : // across nonlinear systems
1166 14652 : return systemBaseNonlinear(0).automaticScaling();
1167 : }
1168 :
1169 : void
1170 363 : SubProblem::hasScalingVector(const unsigned int nl_sys_num)
1171 : {
1172 786 : for (const THREAD_ID tid : make_range(libMesh::n_threads()))
1173 423 : assembly(tid, nl_sys_num).hasScalingVector();
1174 363 : }
1175 :
1176 : void
1177 377715 : SubProblem::clearAllDofIndices()
1178 : {
1179 768334 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1180 390619 : systemBaseNonlinear(nl_sys_num).clearAllDofIndices();
1181 377715 : systemBaseAuxiliary().clearAllDofIndices();
1182 377715 : }
1183 :
1184 : void
1185 316573 : SubProblem::timestepSetup()
1186 : {
1187 661129 : for (auto & map : _pbblf_functors)
1188 355986 : for (auto & pr : map)
1189 11430 : pr.second->timestepSetup();
1190 316573 : }
1191 :
1192 : void
1193 2039946 : SubProblem::customSetup(const ExecFlagType & exec_type)
1194 : {
1195 4261978 : for (auto & map : _pbblf_functors)
1196 2300751 : for (auto & pr : map)
1197 78719 : pr.second->customSetup(exec_type);
1198 2039946 : }
1199 :
1200 : void
1201 3418604 : SubProblem::residualSetup()
1202 : {
1203 7144304 : for (auto & map : _pbblf_functors)
1204 3823122 : for (auto & pr : map)
1205 97422 : pr.second->residualSetup();
1206 3418604 : }
1207 :
1208 : void
1209 540556 : SubProblem::jacobianSetup()
1210 : {
1211 1131041 : for (auto & map : _pbblf_functors)
1212 606971 : for (auto & pr : map)
1213 16486 : pr.second->jacobianSetup();
1214 540556 : }
1215 :
1216 : void
1217 62254 : SubProblem::initialSetup()
1218 : {
1219 62254 : if (_output_functors)
1220 : {
1221 36 : showFunctors();
1222 36 : showFunctorRequestors();
1223 : }
1224 :
1225 130263 : for (const auto & functors : _functors)
1226 375016 : for (const auto & [functor_wrapper_name, functor_wrapper] : functors)
1227 : {
1228 307007 : const auto & [true_functor_type, non_ad_functor, ad_functor] = functor_wrapper;
1229 : mooseAssert(non_ad_functor->wrapsNull() == ad_functor->wrapsNull(), "These must agree");
1230 307007 : const auto functor_name = removeSubstring(functor_wrapper_name, "wraps_");
1231 307007 : if (non_ad_functor->wrapsNull())
1232 0 : mooseError(
1233 : "No functor ever provided with name '",
1234 : functor_name,
1235 : "', which was requested by '",
1236 0 : MooseUtils::join(libmesh_map_find(_functor_to_requestors, functor_wrapper_name), ","),
1237 : "'.");
1238 489934 : if (true_functor_type == TrueFunctorIs::NONAD ? non_ad_functor->ownsWrappedFunctor()
1239 182927 : : ad_functor->ownsWrappedFunctor())
1240 0 : mooseError("Functor envelopes should not own the functors they wrap, but '",
1241 : functor_name,
1242 : "' is owned by the wrapper. Please open a MOOSE issue for help resolving this.");
1243 307007 : }
1244 62254 : }
1245 :
1246 : void
1247 36 : SubProblem::showFunctors() const
1248 : {
1249 36 : _console << "[DBG] Wrapped functors found in Subproblem" << std::endl;
1250 36 : std::string functor_names = "[DBG] ";
1251 284 : for (const auto & functor_pair : _functors[0])
1252 248 : functor_names += std::regex_replace(functor_pair.first, std::regex("wraps_"), "") + " ";
1253 36 : if (functor_names.size())
1254 36 : functor_names.pop_back();
1255 36 : _console << functor_names << std::endl;
1256 36 : }
1257 :
1258 : void
1259 36 : SubProblem::showFunctorRequestors() const
1260 : {
1261 128 : for (const auto & [functor, requestors] : _functor_to_requestors)
1262 : {
1263 92 : _console << "[DBG] Requestors for wrapped functor "
1264 92 : << std::regex_replace(functor, std::regex("wraps_"), "") << std::endl;
1265 92 : _console << "[DBG] " << MooseUtils::join(requestors, " ") << std::endl;
1266 : }
1267 36 : }
1268 :
1269 : bool
1270 550 : SubProblem::hasFunctor(const std::string & name, const THREAD_ID tid) const
1271 : {
1272 : mooseAssert(tid < _functors.size(), "Too large a thread ID");
1273 550 : auto & functors = _functors[tid];
1274 550 : return (functors.find("wraps_" + name) != functors.end());
1275 : }
1276 :
1277 : Moose::CoordinateSystemType
1278 473324641 : SubProblem::getCoordSystem(SubdomainID sid) const
1279 : {
1280 473324641 : return mesh().getCoordSystem(sid);
1281 : }
1282 :
1283 : void
1284 25427893 : SubProblem::reinitFVFace(const THREAD_ID tid, const FaceInfo & fi)
1285 : {
1286 51947720 : for (const auto nl : make_range(numNonlinearSystems()))
1287 26519827 : assembly(tid, nl).reinitFVFace(fi);
1288 25427893 : }
1289 :
1290 : void
1291 374344236 : SubProblem::cacheResidual(const THREAD_ID tid)
1292 : {
1293 374344236 : assembly(tid, currentNlSysNum())
1294 374344236 : .cacheResidual(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1295 374344236 : }
1296 :
1297 : void
1298 38414020 : SubProblem::cacheResidualNeighbor(const THREAD_ID tid)
1299 : {
1300 38414020 : assembly(tid, currentNlSysNum())
1301 38414020 : .cacheResidualNeighbor(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1302 38414020 : }
1303 :
1304 : void
1305 57645873 : SubProblem::addCachedResidual(const THREAD_ID tid)
1306 : {
1307 57645873 : assembly(tid, currentNlSysNum())
1308 57645873 : .addCachedResiduals(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1309 57645873 : }
1310 :
1311 : void
1312 56920459 : SubProblem::cacheJacobian(const THREAD_ID tid)
1313 : {
1314 56920459 : assembly(tid, currentNlSysNum()).cacheJacobian(Assembly::GlobalDataKey{});
1315 56920459 : if (hasNonlocalCoupling())
1316 5880 : assembly(tid, currentNlSysNum()).cacheJacobianNonlocal(Assembly::GlobalDataKey{});
1317 56920459 : }
1318 :
1319 : void
1320 10576 : SubProblem::cacheJacobianNeighbor(const THREAD_ID tid)
1321 : {
1322 10576 : assembly(tid, currentNlSysNum()).cacheJacobianNeighbor(Assembly::GlobalDataKey{});
1323 10576 : }
1324 :
1325 : void
1326 4209834 : SubProblem::addCachedJacobian(const THREAD_ID tid)
1327 : {
1328 4209834 : assembly(tid, currentNlSysNum()).addCachedJacobian(Assembly::GlobalDataKey{});
1329 4209830 : }
1330 :
1331 : void
1332 234 : SubProblem::preparePRefinement()
1333 : {
1334 234 : std::unordered_set<FEFamily> disable_families;
1335 663 : for (const auto & [family, flag] : _family_for_p_refinement)
1336 429 : if (flag)
1337 195 : disable_families.insert(family);
1338 :
1339 486 : for (const auto tid : make_range(libMesh::n_threads()))
1340 504 : for (const auto s : make_range(numNonlinearSystems()))
1341 252 : assembly(tid, s).havePRefinement(disable_families);
1342 :
1343 234 : auto & eq = es();
1344 429 : for (const auto family : disable_families)
1345 585 : for (const auto i : make_range(eq.n_systems()))
1346 : {
1347 390 : auto & system = eq.get_system(i);
1348 390 : auto & dof_map = system.get_dof_map();
1349 936 : for (const auto vg : make_range(system.n_variable_groups()))
1350 : {
1351 546 : const auto & var_group = system.variable_group(vg);
1352 546 : if (var_group.type().family == family)
1353 195 : dof_map.should_p_refine(vg, false);
1354 : }
1355 : }
1356 :
1357 234 : _have_p_refinement = true;
1358 234 : }
1359 :
1360 : bool
1361 464 : SubProblem::doingPRefinement() const
1362 : {
1363 464 : return mesh().doingPRefinement();
1364 : }
1365 :
1366 : void
1367 157903 : SubProblem::markFamilyPRefinement(const InputParameters & params)
1368 : {
1369 157903 : auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
1370 157903 : bool flag = _default_families_without_p_refinement.count(family);
1371 157903 : if (params.isParamValid("disable_p_refinement"))
1372 143 : flag = params.get<bool>("disable_p_refinement");
1373 :
1374 157903 : auto [it, inserted] = _family_for_p_refinement.emplace(family, flag);
1375 157903 : if (!inserted && flag != it->second)
1376 0 : mooseError("'disable_p_refinement' not set consistently for variables in ", family);
1377 157903 : }
1378 :
1379 : void
1380 156189 : SubProblem::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
1381 : {
1382 312378 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1383 156189 : assembly(tid, nl_sys_num).setCurrentLowerDElem(lower_d_elem);
1384 156189 : }
1385 :
1386 : template MooseVariableFEBase &
1387 : SubProblem::getVariableHelper(const THREAD_ID tid,
1388 : const std::string & var_name,
1389 : Moose::VarKindType expected_var_type,
1390 : Moose::VarFieldType expected_var_field_type,
1391 : const std::vector<std::shared_ptr<SolverSystem>> & nls,
1392 : const SystemBase & aux) const;
1393 : template MooseVariableFEBase &
1394 : SubProblem::getVariableHelper(const THREAD_ID tid,
1395 : const std::string & var_name,
1396 : Moose::VarKindType expected_var_type,
1397 : Moose::VarFieldType expected_var_field_type,
1398 : const std::vector<std::unique_ptr<DisplacedSystem>> & nls,
1399 : const SystemBase & aux) const;
|