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 359666 : SubProblem::validParams()
37 : {
38 359666 : InputParameters params = Problem::validParams();
39 :
40 1078998 : params.addParam<bool>(
41 : "default_ghosting",
42 719332 : false,
43 : "Whether or not to use libMesh's default amount of algebraic and geometric ghosting");
44 :
45 1078998 : params.addParamNamesToGroup("default_ghosting", "Advanced");
46 :
47 359666 : 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 65469 : SubProblem::SubProblem(const InputParameters & parameters)
61 : : Problem(parameters),
62 65469 : _factory(_app.getFactory()),
63 130938 : _default_ghosting(getParam<bool>("default_ghosting")),
64 65469 : _currently_computing_jacobian(false),
65 65469 : _currently_computing_residual_and_jacobian(false),
66 65469 : _computing_nonlinear_residual(false),
67 65469 : _currently_computing_residual(false),
68 65469 : _safe_access_tagged_matrices(false),
69 65469 : _safe_access_tagged_vectors(false),
70 65469 : _have_ad_objects(false),
71 65469 : _output_functors(false),
72 130938 : _typed_vector_tags(2),
73 261876 : _have_p_refinement(false)
74 : {
75 65469 : unsigned int n_threads = libMesh::n_threads();
76 65469 : _active_elemental_moose_variables.resize(n_threads);
77 65469 : _has_active_elemental_moose_variables.resize(n_threads);
78 :
79 65469 : _active_fe_var_coupleable_matrix_tags.resize(n_threads);
80 65469 : _active_fe_var_coupleable_vector_tags.resize(n_threads);
81 65469 : _active_sc_var_coupleable_matrix_tags.resize(n_threads);
82 65469 : _active_sc_var_coupleable_vector_tags.resize(n_threads);
83 :
84 65469 : _functors.resize(n_threads);
85 65469 : _pbblf_functors.resize(n_threads);
86 65469 : _functor_to_request_info.resize(n_threads);
87 65469 : }
88 :
89 61087 : SubProblem::~SubProblem() {}
90 :
91 : TagID
92 418623 : SubProblem::addVectorTag(const TagName & tag_name,
93 : const Moose::VectorTagType type /* = Moose::VECTOR_TAG_RESIDUAL */)
94 : {
95 418623 : if (type == Moose::VECTOR_TAG_ANY)
96 0 : mooseError("Vector tag type cannot be VECTOR_TAG_ANY");
97 :
98 418623 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
99 :
100 : // First, see if the tag exists already
101 1623499 : for (const auto & vector_tag : _vector_tags)
102 : {
103 : mooseAssert(_vector_tags[vector_tag._id] == vector_tag, "Vector tags index mismatch");
104 1301171 : if (vector_tag._name == tag_name_upper)
105 : {
106 96295 : 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 96295 : return vector_tag._id;
116 : }
117 : }
118 :
119 : // Doesn't exist - create it
120 322328 : const TagID new_tag_id = _vector_tags.size();
121 322328 : 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 322328 : _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 322328 : _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 322328 : _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 322328 : verifyVectorTags();
131 :
132 322328 : return new_tag_id;
133 418623 : }
134 :
135 : bool
136 328078 : SubProblem::vectorTagExists(const TagName & tag_name) const
137 : {
138 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
139 :
140 328078 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
141 2737979 : for (const auto & vector_tag : _vector_tags)
142 2424530 : if (vector_tag._name == tag_name_upper)
143 14629 : return true;
144 :
145 313449 : return false;
146 328078 : }
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 9512308 : SubProblem::vectorTagNotZeroed(const TagID tag) const
156 : {
157 9512308 : return _not_zeroed_tagged_vectors.count(tag);
158 : }
159 :
160 : const VectorTag &
161 934285961 : SubProblem::getVectorTag(const TagID tag_id) const
162 : {
163 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
164 :
165 934285961 : if (!vectorTagExists(tag_id))
166 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
167 :
168 934285961 : return _vector_tags[tag_id];
169 : }
170 :
171 : std::vector<VectorTag>
172 6604150 : SubProblem::getVectorTags(const std::set<TagID> & tag_ids) const
173 : {
174 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
175 :
176 6604150 : std::vector<VectorTag> tags;
177 6604150 : tags.reserve(tag_ids.size());
178 25646349 : for (const auto & tag_id : tag_ids)
179 19042199 : tags.push_back(getVectorTag(tag_id));
180 6604150 : return tags;
181 0 : }
182 :
183 : const std::vector<VectorTag> &
184 11641945 : SubProblem::getVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
185 : {
186 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
187 :
188 11641945 : if (type == Moose::VECTOR_TAG_ANY)
189 555078 : return _vector_tags;
190 : else
191 11086867 : return _typed_vector_tags[type];
192 : }
193 :
194 : unsigned int
195 8263881 : SubProblem::numVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
196 : {
197 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
198 :
199 8263881 : return getVectorTags(type).size();
200 : }
201 :
202 : TagID
203 6753331 : SubProblem::getVectorTagID(const TagName & tag_name) const
204 : {
205 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
206 :
207 6753331 : const auto tag_name_upper = MooseUtils::toUpper(tag_name);
208 6753331 : const auto search = _vector_tags_name_map.find(tag_name_upper);
209 6753331 : if (search != _vector_tags_name_map.end())
210 13506630 : 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 16 : : "";
217 16 : mooseError("Vector tag '", tag_name_upper, "' does not exist", message);
218 6753315 : }
219 :
220 : TagName
221 165125 : SubProblem::vectorTagName(const TagID tag_id) const
222 : {
223 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
224 165125 : if (!vectorTagExists(tag_id))
225 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
226 :
227 165125 : return _vector_tags[tag_id]._name;
228 : }
229 :
230 : Moose::VectorTagType
231 2511574695 : SubProblem::vectorTagType(const TagID tag_id) const
232 : {
233 : mooseAssert(verifyVectorTags(), "Vector tag storage invalid");
234 2511574695 : if (!vectorTagExists(tag_id))
235 0 : mooseError("Vector tag with ID ", tag_id, " does not exist");
236 :
237 2511574695 : return _vector_tags[tag_id]._type;
238 : }
239 :
240 : bool
241 322328 : SubProblem::verifyVectorTags() const
242 : {
243 1460934 : for (TagID tag_id = 0; tag_id < _vector_tags.size(); ++tag_id)
244 : {
245 1138606 : const auto & vector_tag = _vector_tags[tag_id];
246 :
247 1138606 : if (vector_tag._id != tag_id)
248 0 : mooseError("Vector tag ", vector_tag._id, " id mismatch in _vector_tags");
249 1138606 : if (vector_tag._type == Moose::VECTOR_TAG_ANY)
250 0 : mooseError("Vector tag '", vector_tag._name, "' has type VECTOR_TAG_ANY");
251 :
252 1138606 : const auto search = _vector_tags_name_map.find(vector_tag._name);
253 1138606 : if (search == _vector_tags_name_map.end())
254 0 : mooseError("Vector tag ", vector_tag._id, " is not in _vector_tags_name_map");
255 1138606 : else if (search->second != tag_id)
256 0 : mooseError("Vector tag ", vector_tag._id, " has incorrect id in _vector_tags_name_map");
257 :
258 1138606 : unsigned int found_in_type = 0;
259 4265262 : for (TagTypeID tag_type_id = 0; tag_type_id < _typed_vector_tags[vector_tag._type].size();
260 : ++tag_type_id)
261 : {
262 3126656 : const auto & vector_tag_type = _typed_vector_tags[vector_tag._type][tag_type_id];
263 3126656 : if (vector_tag_type == vector_tag)
264 : {
265 1138606 : ++found_in_type;
266 1138606 : 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 1138606 : if (found_in_type == 0)
272 0 : mooseError("Vector tag ", tag_id, " not found in _typed_vector_tags");
273 1138606 : if (found_in_type > 1)
274 0 : mooseError("Vector tag ", tag_id, " found multiple times in _typed_vector_tags");
275 : }
276 :
277 322328 : unsigned int num_typed_vector_tags = 0;
278 966984 : for (const auto & typed_vector_tags : _typed_vector_tags)
279 644656 : num_typed_vector_tags += typed_vector_tags.size();
280 322328 : if (num_typed_vector_tags != _vector_tags.size())
281 0 : mooseError("Size mismatch between _vector_tags and _typed_vector_tags");
282 322328 : if (_vector_tags_name_map.size() != _vector_tags.size())
283 0 : mooseError("Size mismatch between _vector_tags and _vector_tags_name_map");
284 :
285 322328 : return true;
286 : }
287 :
288 : void
289 3268424 : SubProblem::selectVectorTagsFromSystem(const SystemBase & system,
290 : const std::vector<VectorTag> & input_vector_tags,
291 : std::set<TagID> & selected_tags)
292 : {
293 3268424 : selected_tags.clear();
294 12734603 : for (const auto & vector_tag : input_vector_tags)
295 9466179 : if (system.hasVector(vector_tag._id))
296 9464033 : selected_tags.insert(vector_tag._id);
297 3268424 : }
298 :
299 : void
300 5738 : SubProblem::selectMatrixTagsFromSystem(const SystemBase & system,
301 : const std::map<TagName, TagID> & input_matrix_tags,
302 : std::set<TagID> & selected_tags)
303 : {
304 5738 : selected_tags.clear();
305 11985 : for (const auto & matrix_tag_pair : input_matrix_tags)
306 6247 : if (system.hasMatrix(matrix_tag_pair.second))
307 5762 : selected_tags.insert(matrix_tag_pair.second);
308 5738 : }
309 :
310 : TagID
311 127824 : SubProblem::addMatrixTag(TagName tag_name)
312 : {
313 127824 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
314 127824 : auto existing_tag = _matrix_tag_name_to_tag_id.find(tag_name_upper);
315 127824 : if (existing_tag == _matrix_tag_name_to_tag_id.end())
316 : {
317 127281 : auto tag_id = _matrix_tag_name_to_tag_id.size();
318 :
319 127281 : _matrix_tag_name_to_tag_id[tag_name_upper] = tag_id;
320 :
321 127281 : _matrix_tag_id_to_tag_name[tag_id] = tag_name_upper;
322 : }
323 :
324 255648 : return _matrix_tag_name_to_tag_id.at(tag_name_upper);
325 127824 : }
326 :
327 : bool
328 301321 : SubProblem::matrixTagExists(const TagName & tag_name) const
329 : {
330 301321 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
331 :
332 602642 : return _matrix_tag_name_to_tag_id.find(tag_name_upper) != _matrix_tag_name_to_tag_id.end();
333 301321 : }
334 :
335 : bool
336 1645752 : SubProblem::matrixTagExists(TagID tag_id) const
337 : {
338 1645752 : return _matrix_tag_id_to_tag_name.find(tag_id) != _matrix_tag_id_to_tag_name.end();
339 : }
340 :
341 : TagID
342 299911 : SubProblem::getMatrixTagID(const TagName & tag_name) const
343 : {
344 299911 : auto tag_name_upper = MooseUtils::toUpper(tag_name);
345 :
346 299911 : 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 599814 : return _matrix_tag_name_to_tag_id.at(tag_name_upper);
354 299907 : }
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 654687 : SubProblem::setActiveFEVariableCoupleableMatrixTags(std::set<TagID> & mtags, const THREAD_ID tid)
364 : {
365 654687 : _active_fe_var_coupleable_matrix_tags[tid] = mtags;
366 654687 : }
367 :
368 : void
369 7639033 : SubProblem::setActiveFEVariableCoupleableVectorTags(std::set<TagID> & vtags, const THREAD_ID tid)
370 : {
371 7639033 : _active_fe_var_coupleable_vector_tags[tid] = vtags;
372 15411122 : for (const auto sys_num : make_range(numSolverSystems()))
373 7772089 : systemBaseSolver(sys_num).setActiveVariableCoupleableVectorTags(vtags, tid);
374 7639033 : systemBaseAuxiliary().setActiveVariableCoupleableVectorTags(vtags, tid);
375 7639033 : }
376 :
377 : void
378 297733 : SubProblem::clearActiveFEVariableCoupleableVectorTags(const THREAD_ID tid)
379 : {
380 297733 : _active_fe_var_coupleable_vector_tags[tid].clear();
381 297733 : }
382 :
383 : void
384 297733 : SubProblem::clearActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid)
385 : {
386 297733 : _active_fe_var_coupleable_matrix_tags[tid].clear();
387 297733 : }
388 :
389 : const std::set<TagID> &
390 1945160846 : SubProblem::getActiveFEVariableCoupleableMatrixTags(const THREAD_ID tid) const
391 : {
392 1945160846 : 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 569980 : SubProblem::getActiveScalarVariableCoupleableMatrixTags(const THREAD_ID tid) const
432 : {
433 569980 : 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 11808066 : SubProblem::setActiveElementalMooseVariables(const std::set<MooseVariableFEBase *> & moose_vars,
444 : const THREAD_ID tid)
445 : {
446 11808066 : if (!moose_vars.empty())
447 : {
448 11362174 : _has_active_elemental_moose_variables[tid] = 1;
449 11362174 : _active_elemental_moose_variables[tid] = moose_vars;
450 : }
451 11808066 : }
452 :
453 : const std::set<MooseVariableFEBase *> &
454 1276755168 : SubProblem::getActiveElementalMooseVariables(const THREAD_ID tid) const
455 : {
456 1276755168 : return _active_elemental_moose_variables[tid];
457 : }
458 :
459 : bool
460 1321868244 : SubProblem::hasActiveElementalMooseVariables(const THREAD_ID tid) const
461 : {
462 1321868244 : return _has_active_elemental_moose_variables[tid];
463 : }
464 :
465 : void
466 4874491 : SubProblem::clearActiveElementalMooseVariables(const THREAD_ID tid)
467 : {
468 4874491 : _has_active_elemental_moose_variables[tid] = 0;
469 4874491 : _active_elemental_moose_variables[tid].clear();
470 4874491 : }
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 68776 : SubProblem::storeSubdomainMatPropName(SubdomainID block_id, const std::string & name)
584 : {
585 68776 : _map_block_material_props[block_id].insert(name);
586 68776 : }
587 :
588 : void
589 64766 : SubProblem::storeBoundaryMatPropName(BoundaryID boundary_id, const std::string & name)
590 : {
591 64766 : _map_boundary_material_props[boundary_id].insert(name);
592 64766 : }
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 45995 : SubProblem::storeSubdomainDelayedCheckMatProp(const std::string & requestor,
608 : SubdomainID block_id,
609 : const std::string & name)
610 : {
611 45995 : _map_block_material_props_check[block_id].insert(std::make_pair(requestor, name));
612 45995 : }
613 :
614 : void
615 6267 : SubProblem::storeBoundaryDelayedCheckMatProp(const std::string & requestor,
616 : BoundaryID boundary_id,
617 : const std::string & name)
618 : {
619 6267 : _map_boundary_material_props_check[boundary_id].insert(std::make_pair(requestor, name));
620 6267 : }
621 :
622 : void
623 61260 : SubProblem::checkBlockMatProps()
624 : {
625 : // Variable for storing all available blocks/boundaries from the mesh
626 61260 : std::set<SubdomainID> all_ids(mesh().meshSubdomains());
627 :
628 61260 : std::stringstream errors;
629 :
630 : // Loop through the properties to check
631 67619 : for (const auto & check_it : _map_block_material_props_check)
632 : {
633 : // The current id for the property being checked (BoundaryID || BlockID)
634 6359 : SubdomainID check_id = check_it.first;
635 :
636 12718 : std::set<SubdomainID> check_ids = {check_id};
637 :
638 : // Loop through all the block/boundary ids
639 12718 : for (const auto & id : check_ids)
640 : {
641 : // Loop through all the stored properties
642 50127 : 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 43874 : if (_map_block_material_props[id].count(prop_it.second) == 0 &&
648 43874 : _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 6359 : }
659 :
660 61260 : if (!errors.str().empty())
661 40 : mooseError(errors.str());
662 61220 : }
663 :
664 : void
665 61220 : SubProblem::checkBoundaryMatProps()
666 : {
667 : // Variable for storing the value for ANY_BOUNDARY_ID
668 61220 : BoundaryID any_id = Moose::ANY_BOUNDARY_ID;
669 :
670 : // Variable for storing all available blocks/boundaries from the mesh
671 61220 : std::set<BoundaryID> all_ids(mesh().getBoundaryIDs());
672 :
673 61220 : std::stringstream errors;
674 :
675 : // Loop through the properties to check
676 63871 : for (const auto & check_it : _map_boundary_material_props_check)
677 : {
678 : // The current id for the property being checked (BoundaryID || BlockID)
679 2651 : 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 5302 : std::set<BoundaryID> check_ids{check_id};
684 2651 : if (check_id == any_id)
685 0 : check_ids = all_ids;
686 :
687 : // Loop through all the block/boundary ids
688 5302 : for (const auto & id : check_ids)
689 : {
690 : // Loop through all the stored properties
691 8918 : 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 6267 : if (_map_boundary_material_props[id].count(prop_it.second) == 0 &&
697 4966 : _map_boundary_material_props[any_id].count(prop_it.second) == 0 &&
698 23782 : _zero_boundary_material_props[id].count(prop_it.second) == 0 &&
699 6282 : _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 2651 : }
710 :
711 61220 : if (!errors.str().empty())
712 12 : mooseError(errors.str());
713 61208 : }
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 64830 : SubProblem::markMatPropRequested(const std::string & prop_name)
725 : {
726 64830 : _material_property_requested.insert(prop_name);
727 64830 : }
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 50608 : SubProblem::addConsumedPropertyName(const MooseObjectName & obj_name, const std::string & prop_name)
737 : {
738 50608 : _consumed_material_properties[obj_name].insert(prop_name);
739 50608 : }
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 90 : 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 145540753 : SubProblem::setCurrentBoundaryID(BoundaryID bid, const THREAD_ID tid)
790 : {
791 292382157 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
792 146841404 : assembly(tid, nl_sys_num).setCurrentBoundaryID(bid);
793 145540753 : }
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 4753903 : 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 4753903 : MooseVariableFEBase * var = nullptr;
827 :
828 4753903 : const auto [var_in_sys, sys_num] = determineSolverSystem(var_name);
829 :
830 : // First check that the variable is found on the expected system.
831 4753903 : if (expected_var_type == Moose::VarKindType::VAR_ANY)
832 : {
833 2584658 : if (var_in_sys)
834 1178764 : var = &(systems[sys_num]->getVariable(tid, var_name));
835 1405894 : else if (aux.hasVariable(var_name))
836 1405894 : var = &(aux.getVariable(tid, var_name));
837 : else
838 0 : mooseError("Unknown variable " + var_name);
839 : }
840 2363253 : else if (expected_var_type == Moose::VarKindType::VAR_SOLVER && var_in_sys &&
841 194008 : systems[sys_num]->hasVariable(var_name))
842 194008 : var = &(systems[sys_num]->getVariable(tid, var_name));
843 1975237 : else if (expected_var_type == Moose::VarKindType::VAR_AUXILIARY && aux.hasVariable(var_name))
844 1975237 : 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 6986272 : if ((expected_var_field_type == Moose::VarFieldType::VAR_FIELD_ANY) ||
860 2232369 : (expected_var_field_type == var->fieldType()))
861 4753895 : 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 307159 : 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 614318 : 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 307159 : assembly(tid, nl_sys_num).reinitElemFaceRef(elem, side, tolerance, pts, weights);
897 :
898 307159 : auto & nl = systemBaseNonlinear(nl_sys_num);
899 :
900 : // Actually get the dof indices in the moose variables
901 307159 : nl.prepare(tid);
902 :
903 : // Let's finally compute our variable values!
904 307159 : nl.reinitElemFace(elem, side, tid);
905 : }
906 :
907 : // do same for aux as for nl
908 307159 : systemBaseAuxiliary().prepare(tid);
909 307159 : 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 307159 : auto & current_assembly = assembly(tid, currentNlSysNum());
914 307159 : if (currentlyComputingJacobian() || currentlyComputingResidualAndJacobian())
915 101292 : current_assembly.prepareJacobianBlock();
916 307159 : if (!currentlyComputingJacobian())
917 205867 : current_assembly.prepareResidual();
918 307159 : }
919 :
920 : void
921 307159 : 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 614318 : 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 307159 : assembly(tid, nl_sys_num)
936 307159 : .reinitNeighborFaceRef(neighbor_elem, neighbor_side, tolerance, pts, weights);
937 :
938 307159 : auto & nl = systemBaseNonlinear(nl_sys_num);
939 :
940 : // Actually get the dof indices in the moose variables
941 307159 : nl.prepareNeighbor(tid);
942 :
943 : // Let's finally compute our variable values!
944 307159 : nl.reinitNeighborFace(neighbor_elem, neighbor_side, tid);
945 : }
946 :
947 : // do same for aux as for nl
948 307159 : systemBaseAuxiliary().prepareNeighbor(tid);
949 307159 : 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 307159 : assembly(tid, currentNlSysNum()).prepareNeighbor();
954 307159 : }
955 :
956 : void
957 326016 : 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 652032 : 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 326016 : assembly(tid, nl_sys_num).reinitLowerDElem(elem, pts, weights);
967 :
968 326016 : auto & nl = systemBaseNonlinear(nl_sys_num);
969 :
970 : // Actually get the dof indices in the moose variables
971 326016 : 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 326016 : assembly(tid, nl_sys_num).prepareLowerD();
976 :
977 : // Let's finally compute our variable values!
978 326016 : nl.reinitLowerD(tid);
979 : }
980 :
981 : // do same for aux as for nl
982 326016 : systemBaseAuxiliary().prepareLowerD(tid);
983 326016 : systemBaseAuxiliary().reinitLowerD(tid);
984 326016 : }
985 :
986 : void
987 284381 : SubProblem::reinitNeighborLowerDElem(const Elem * elem, const THREAD_ID tid)
988 : {
989 568762 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
990 284381 : assembly(tid, nl_sys_num).reinitNeighborLowerDElem(elem);
991 284381 : }
992 :
993 : void
994 568762 : SubProblem::reinitMortarElem(const Elem * elem, const THREAD_ID tid)
995 : {
996 1137524 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
997 568762 : assembly(tid, nl_sys_num).reinitMortarElem(elem);
998 568762 : }
999 :
1000 : void
1001 34181 : SubProblem::cloneAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
1002 : {
1003 34181 : EquationSystems & eq = es();
1004 34181 : const auto n_sys = eq.n_systems();
1005 :
1006 34181 : auto pr = _root_alg_gf_to_sys_clones.emplace(
1007 34181 : &algebraic_gf, std::vector<std::shared_ptr<GhostingFunctor>>(n_sys - 1));
1008 : mooseAssert(pr.second, "We are adding a duplicate algebraic ghosting functor");
1009 34181 : auto & clones_vec = pr.first->second;
1010 :
1011 68576 : for (MooseIndex(n_sys) i = 1; i < n_sys; ++i)
1012 : {
1013 34395 : DofMap & dof_map = eq.get_system(i).get_dof_map();
1014 34395 : std::shared_ptr<GhostingFunctor> clone_alg_gf = algebraic_gf.clone();
1015 68790 : std::dynamic_pointer_cast<RelationshipManager>(clone_alg_gf)
1016 34395 : ->init(mesh(), *algebraic_gf.get_mesh(), &dof_map);
1017 34395 : dof_map.add_algebraic_ghosting_functor(clone_alg_gf, to_mesh);
1018 34395 : clones_vec[i - 1] = clone_alg_gf;
1019 34395 : }
1020 34181 : }
1021 :
1022 : void
1023 34181 : SubProblem::addAlgebraicGhostingFunctor(GhostingFunctor & algebraic_gf, bool to_mesh)
1024 : {
1025 34181 : EquationSystems & eq = es();
1026 34181 : const auto n_sys = eq.n_systems();
1027 34181 : if (!n_sys)
1028 0 : return;
1029 :
1030 34181 : eq.get_system(0).get_dof_map().add_algebraic_ghosting_functor(algebraic_gf, to_mesh);
1031 34181 : cloneAlgebraicGhostingFunctor(algebraic_gf, to_mesh);
1032 : }
1033 :
1034 : void
1035 45994 : SubProblem::cloneCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
1036 : {
1037 45994 : const std::size_t num_nl_sys = numNonlinearSystems();
1038 :
1039 45994 : auto pr = _root_coupling_gf_to_sys_clones.emplace(
1040 45994 : &coupling_gf, std::vector<std::shared_ptr<GhostingFunctor>>(num_nl_sys - 1));
1041 : mooseAssert(pr.second, "We are adding a duplicate coupling functor");
1042 45994 : auto & clones_vec = pr.first->second;
1043 :
1044 46193 : 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 45994 : }
1054 :
1055 : void
1056 47258 : SubProblem::addCouplingGhostingFunctor(GhostingFunctor & coupling_gf, bool to_mesh)
1057 : {
1058 47258 : const auto num_nl_sys = numNonlinearSystems();
1059 47258 : if (!num_nl_sys)
1060 1264 : return;
1061 :
1062 45994 : systemBaseNonlinear(0).system().get_dof_map().add_coupling_functor(coupling_gf, to_mesh);
1063 45994 : 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 67063 : SubProblem::automaticScaling(bool automatic_scaling)
1156 : {
1157 133085 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1158 66022 : systemBaseNonlinear(nl_sys_num).automaticScaling(automatic_scaling);
1159 67063 : }
1160 :
1161 : bool
1162 14955 : SubProblem::automaticScaling() const
1163 : {
1164 : // Currently going to assume that we are applying or not applying automatic scaling consistently
1165 : // across nonlinear systems
1166 14955 : 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 379596 : SubProblem::clearAllDofIndices()
1178 : {
1179 772096 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1180 392500 : systemBaseNonlinear(nl_sys_num).clearAllDofIndices();
1181 379596 : systemBaseAuxiliary().clearAllDofIndices();
1182 379596 : }
1183 :
1184 : void
1185 318725 : SubProblem::timestepSetup()
1186 : {
1187 665648 : for (auto & map : _pbblf_functors)
1188 358628 : for (auto & pr : map)
1189 11705 : pr.second->timestepSetup();
1190 318725 : }
1191 :
1192 : void
1193 2052147 : SubProblem::customSetup(const ExecFlagType & exec_type)
1194 : {
1195 4287461 : for (auto & map : _pbblf_functors)
1196 2317643 : for (auto & pr : map)
1197 82329 : pr.second->customSetup(exec_type);
1198 2052147 : }
1199 :
1200 : void
1201 3434089 : SubProblem::residualSetup()
1202 : {
1203 7176418 : for (auto & map : _pbblf_functors)
1204 3841474 : for (auto & pr : map)
1205 99145 : pr.second->residualSetup();
1206 3434089 : }
1207 :
1208 : void
1209 543033 : SubProblem::jacobianSetup()
1210 : {
1211 1136187 : for (auto & map : _pbblf_functors)
1212 610763 : for (auto & pr : map)
1213 17609 : pr.second->jacobianSetup();
1214 543033 : }
1215 :
1216 : void
1217 62996 : SubProblem::initialSetup()
1218 : {
1219 62996 : if (_output_functors)
1220 : {
1221 36 : showFunctors();
1222 36 : showFunctorRequestors();
1223 : }
1224 :
1225 131821 : for (const auto & functors : _functors)
1226 382022 : for (const auto & [functor_wrapper_name, functor_wrapper] : functors)
1227 : {
1228 313197 : 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 313197 : const auto functor_name = removeSubstring(functor_wrapper_name, "wraps_");
1231 313197 : 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 501145 : if (true_functor_type == TrueFunctorIs::NONAD ? non_ad_functor->ownsWrappedFunctor()
1239 187948 : : 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 313197 : }
1244 62996 : }
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 276 : _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 474244219 : SubProblem::getCoordSystem(SubdomainID sid) const
1279 : {
1280 474244219 : return mesh().getCoordSystem(sid);
1281 : }
1282 :
1283 : void
1284 25448818 : SubProblem::reinitFVFace(const THREAD_ID tid, const FaceInfo & fi)
1285 : {
1286 51989570 : for (const auto nl : make_range(numNonlinearSystems()))
1287 26540752 : assembly(tid, nl).reinitFVFace(fi);
1288 25448818 : }
1289 :
1290 : void
1291 375022236 : SubProblem::cacheResidual(const THREAD_ID tid)
1292 : {
1293 375022236 : assembly(tid, currentNlSysNum())
1294 375022236 : .cacheResidual(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1295 375022236 : }
1296 :
1297 : void
1298 38441650 : SubProblem::cacheResidualNeighbor(const THREAD_ID tid)
1299 : {
1300 38441650 : assembly(tid, currentNlSysNum())
1301 38441650 : .cacheResidualNeighbor(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1302 38441650 : }
1303 :
1304 : void
1305 57718918 : SubProblem::addCachedResidual(const THREAD_ID tid)
1306 : {
1307 57718918 : assembly(tid, currentNlSysNum())
1308 57718918 : .addCachedResiduals(Assembly::GlobalDataKey{}, currentResidualVectorTags());
1309 57718918 : }
1310 :
1311 : void
1312 57010405 : SubProblem::cacheJacobian(const THREAD_ID tid)
1313 : {
1314 57010405 : assembly(tid, currentNlSysNum()).cacheJacobian(Assembly::GlobalDataKey{});
1315 57010405 : if (hasNonlocalCoupling())
1316 5880 : assembly(tid, currentNlSysNum()).cacheJacobianNonlocal(Assembly::GlobalDataKey{});
1317 57010405 : }
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 4219445 : SubProblem::addCachedJacobian(const THREAD_ID tid)
1327 : {
1328 4219445 : assembly(tid, currentNlSysNum()).addCachedJacobian(Assembly::GlobalDataKey{});
1329 4219441 : }
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 159120 : SubProblem::markFamilyPRefinement(const InputParameters & params)
1368 : {
1369 159120 : auto family = Utility::string_to_enum<FEFamily>(params.get<MooseEnum>("family"));
1370 159120 : bool flag = _default_families_without_p_refinement.count(family);
1371 318240 : if (params.isParamValid("disable_p_refinement"))
1372 143 : flag = params.get<bool>("disable_p_refinement");
1373 :
1374 159120 : auto [it, inserted] = _family_for_p_refinement.emplace(family, flag);
1375 159120 : if (!inserted && flag != it->second)
1376 0 : mooseError("'disable_p_refinement' not set consistently for variables in ", family);
1377 159120 : }
1378 :
1379 : void
1380 156203 : SubProblem::setCurrentLowerDElem(const Elem * const lower_d_elem, const THREAD_ID tid)
1381 : {
1382 312406 : for (const auto nl_sys_num : make_range(numNonlinearSystems()))
1383 156203 : assembly(tid, nl_sys_num).setCurrentLowerDElem(lower_d_elem);
1384 156203 : }
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;
|