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 "TaggingInterface.h"
11 : #include "Conversion.h"
12 : #include "FEProblem.h"
13 : #include "Assembly.h"
14 : #include "ReferenceResidualConvergence.h"
15 : #include "ReferenceResidualProblem.h"
16 :
17 : #include "libmesh/dense_vector.h"
18 :
19 : InputParameters
20 1720624 : TaggingInterface::validParams()
21 : {
22 :
23 1720624 : InputParameters params = emptyInputParameters();
24 :
25 : // These are the default names for tags, but users will be able to add their own
26 3441248 : MultiMooseEnum vtags("nontime time", "nontime", true);
27 3441248 : MultiMooseEnum mtags("nontime system", "system", true);
28 :
29 5161872 : params.addParam<bool>(
30 3441248 : "matrix_only", false, "Whether this object is only doing assembly to matrices (no vectors)");
31 :
32 6882496 : params.addParam<MultiMooseEnum>(
33 : "vector_tags", vtags, "The tag for the vectors this Kernel should fill");
34 :
35 6882496 : params.addParam<MultiMooseEnum>(
36 : "matrix_tags", mtags, "The tag for the matrices this Kernel should fill");
37 :
38 6882496 : params.addParam<std::vector<TagName>>("extra_vector_tags",
39 : "The extra tags for the vectors this Kernel should fill");
40 :
41 6882496 : params.addParam<std::vector<TagName>>(
42 : "absolute_value_vector_tags",
43 : "The tags for the vectors this residual object should fill with the "
44 : "absolute value of the residual contribution");
45 :
46 6882496 : params.addParam<std::vector<TagName>>("extra_matrix_tags",
47 : "The extra tags for the matrices this Kernel should fill");
48 :
49 5161872 : params.addParamNamesToGroup("vector_tags matrix_tags extra_vector_tags extra_matrix_tags "
50 : "absolute_value_vector_tags matrix_only",
51 : "Contribution to tagged field data");
52 :
53 3441248 : return params;
54 1720624 : }
55 :
56 192287 : TaggingInterface::TaggingInterface(const MooseObject * moose_object)
57 576861 : : _subproblem(*moose_object->parameters().getCheckedPointerParam<SubProblem *>("_subproblem")),
58 192287 : _moose_object(*moose_object),
59 384574 : _tag_params(_moose_object.parameters())
60 : {
61 192287 : auto & vector_tag_names = _tag_params.get<MultiMooseEnum>("vector_tags");
62 :
63 192287 : if (!vector_tag_names.isValid())
64 : {
65 68 : if (!_tag_params.get<bool>("matrix_only"))
66 3 : mooseError("MUST provide at least one vector_tag for Kernel: ", _moose_object.name());
67 : }
68 : else
69 : {
70 384466 : for (auto & vector_tag_name : vector_tag_names)
71 : {
72 192253 : const TagID vector_tag_id = _subproblem.getVectorTagID(vector_tag_name.name());
73 192247 : if (_subproblem.vectorTagType(vector_tag_id) != Moose::VECTOR_TAG_RESIDUAL)
74 0 : mooseError("Vector tag '",
75 0 : vector_tag_name.name(),
76 : "' for Kernel '",
77 0 : _moose_object.name(),
78 : "' is not a residual vector tag");
79 192247 : _vector_tags.insert(vector_tag_id);
80 : }
81 : }
82 :
83 : // Add extra vector tags. These tags should be created in the System already, otherwise
84 : // we can not add the extra tags
85 192278 : auto & extra_vector_tags = _tag_params.get<std::vector<TagName>>("extra_vector_tags");
86 :
87 194808 : for (auto & vector_tag_name : extra_vector_tags)
88 : {
89 2530 : const TagID vector_tag_id = _subproblem.getVectorTagID(vector_tag_name);
90 2530 : if (_subproblem.vectorTagType(vector_tag_id) != Moose::VECTOR_TAG_RESIDUAL)
91 0 : mooseError("Extra vector tag '",
92 : vector_tag_name,
93 : "' for Kernel '",
94 0 : _moose_object.name(),
95 : "' is not a residual vector tag");
96 2530 : _vector_tags.insert(vector_tag_id);
97 : }
98 :
99 : // Add absolue value vector tags. These tags should be created in the System already, otherwise
100 : // we can not add the extra tags
101 192278 : auto & abs_vector_tags = _tag_params.get<std::vector<TagName>>("absolute_value_vector_tags");
102 :
103 193058 : for (auto & vector_tag_name : abs_vector_tags)
104 : {
105 792 : const TagID vector_tag_id = _subproblem.getVectorTagID(vector_tag_name);
106 792 : if (_subproblem.vectorTagType(vector_tag_id) != Moose::VECTOR_TAG_RESIDUAL)
107 12 : mooseError("Absolute value vector tag '",
108 : vector_tag_name,
109 : "' for Kernel '",
110 12 : _moose_object.name(),
111 : "' is not a residual vector tag");
112 780 : _abs_vector_tags.insert(vector_tag_id);
113 : }
114 :
115 192266 : auto & matrix_tag_names = _tag_params.get<MultiMooseEnum>("matrix_tags");
116 :
117 192266 : if (matrix_tag_names.isValid())
118 471438 : for (auto & matrix_tag_name : matrix_tag_names)
119 279175 : _matrix_tags.insert(_subproblem.getMatrixTagID(matrix_tag_name.name()));
120 :
121 192263 : auto & extra_matrix_tags = _tag_params.get<std::vector<TagName>>("extra_matrix_tags");
122 :
123 193757 : for (auto & matrix_tag_name : extra_matrix_tags)
124 1494 : _matrix_tags.insert(_subproblem.getMatrixTagID(matrix_tag_name));
125 :
126 192263 : _re_blocks.resize(_vector_tags.size());
127 192263 : _absre_blocks.resize(_abs_vector_tags.size());
128 192263 : _ke_blocks.resize(_matrix_tags.size());
129 :
130 : const auto * const fe_problem =
131 769052 : moose_object->parameters().getCheckedPointerParam<FEProblemBase *>("_fe_problem_base");
132 :
133 670152 : for (const auto & conv : fe_problem->getConvergenceObjects())
134 : {
135 477889 : const auto * const ref_conv = dynamic_cast<const ReferenceResidualConvergence *>(conv.get());
136 477889 : if (ref_conv)
137 : {
138 2265 : const auto reference_tag = ref_conv->referenceVectorTagID({});
139 : auto create_tags_split =
140 4530 : [reference_tag](const auto & tags, auto & non_ref_tags, auto & ref_tags)
141 : {
142 7908 : for (const auto tag : tags)
143 3378 : if (tag == reference_tag)
144 1113 : ref_tags.insert(tag);
145 : else
146 2265 : non_ref_tags.insert(tag);
147 4530 : };
148 2265 : create_tags_split(_vector_tags, _non_ref_vector_tags, _ref_vector_tags);
149 2265 : create_tags_split(_abs_vector_tags, _non_ref_abs_vector_tags, _ref_abs_vector_tags);
150 : }
151 : else
152 : {
153 475624 : _non_ref_vector_tags = _vector_tags;
154 475624 : _non_ref_abs_vector_tags = _abs_vector_tags;
155 : }
156 : }
157 192263 : }
158 :
159 : #ifdef MOOSE_KOKKOS_ENABLED
160 387727 : TaggingInterface::TaggingInterface(const TaggingInterface & object,
161 387727 : const Moose::Kokkos::FunctorCopy &)
162 387727 : : _subproblem(object._subproblem),
163 387727 : _moose_object(object._moose_object),
164 387727 : _tag_params(object._tag_params)
165 : {
166 387727 : }
167 : #endif
168 :
169 : void
170 0 : TaggingInterface::useVectorTag(const TagName & tag_name, VectorTagsKey)
171 : {
172 0 : if (!_subproblem.vectorTagExists(tag_name))
173 0 : mooseError("Vector tag ", tag_name, " does not exist in system");
174 :
175 0 : _vector_tags.insert(_subproblem.getVectorTagID(tag_name));
176 0 : }
177 :
178 : void
179 0 : TaggingInterface::useMatrixTag(const TagName & tag_name, MatrixTagsKey)
180 : {
181 0 : if (!_subproblem.matrixTagExists(tag_name))
182 0 : mooseError("Matrix tag ", tag_name, " does not exist in system");
183 :
184 0 : _matrix_tags.insert(_subproblem.getMatrixTagID(tag_name));
185 0 : }
186 :
187 : void
188 3174 : TaggingInterface::useVectorTag(TagID tag_id, VectorTagsKey)
189 : {
190 3174 : if (!_subproblem.vectorTagExists(tag_id))
191 0 : mooseError("Vector tag ", tag_id, " does not exist in system");
192 :
193 3174 : _vector_tags.insert(tag_id);
194 3174 : }
195 :
196 : void
197 5120 : TaggingInterface::useMatrixTag(TagID tag_id, MatrixTagsKey)
198 : {
199 5120 : if (!_subproblem.matrixTagExists(tag_id))
200 0 : mooseError("Matrix tag ", tag_id, " does not exist in system");
201 :
202 5120 : _matrix_tags.insert(tag_id);
203 5120 : }
204 :
205 : void
206 664429643 : TaggingInterface::prepareVectorTag(Assembly & assembly, const unsigned int ivar)
207 : {
208 664429643 : prepareVectorTagInternal(assembly, ivar, _vector_tags, _abs_vector_tags);
209 664429643 : }
210 :
211 : void
212 0 : TaggingInterface::prepareVectorTag(Assembly & assembly,
213 : const unsigned int ivar,
214 : const ResidualTagType tag_type)
215 : {
216 0 : if (tag_type == ResidualTagType::NonReference)
217 0 : prepareVectorTagInternal(assembly, ivar, _non_ref_vector_tags, _non_ref_abs_vector_tags);
218 : else
219 0 : prepareVectorTagInternal(assembly, ivar, _ref_vector_tags, _ref_abs_vector_tags);
220 0 : }
221 :
222 : void
223 664429643 : TaggingInterface::prepareVectorTagInternal(Assembly & assembly,
224 : const unsigned int ivar,
225 : const std::set<TagID> & vector_tags,
226 : const std::set<TagID> & absolute_value_vector_tags)
227 : {
228 1328859286 : auto prepare = [this, ivar, &assembly](auto & re_blocks, const auto & tags)
229 : {
230 1328859286 : re_blocks.clear();
231 1328859286 : re_blocks.reserve(tags.size());
232 1997525891 : for (const auto tag_id : tags)
233 : {
234 668666605 : const auto & tag = _subproblem.getVectorTag(tag_id);
235 668666605 : re_blocks.push_back(&assembly.residualBlock(ivar, Assembly::LocalDataKey{}, tag._type_id));
236 : }
237 1328859286 : };
238 :
239 664429643 : prepare(_re_blocks, vector_tags);
240 664429643 : prepare(_absre_blocks, absolute_value_vector_tags);
241 :
242 1328859286 : _local_re.resize(_re_blocks.empty()
243 0 : ? (_absre_blocks.empty() ? std::size_t(0) : _absre_blocks[0]->size())
244 664429643 : : _re_blocks[0]->size());
245 664429643 : }
246 :
247 : void
248 15445455 : TaggingInterface::prepareVectorTagNeighbor(Assembly & assembly, unsigned int ivar)
249 : {
250 15445455 : _re_blocks.resize(_vector_tags.size());
251 : mooseAssert(_vector_tags.size() >= 1, "we need at least one active tag");
252 15445455 : auto vector_tag = _vector_tags.begin();
253 30892206 : for (MooseIndex(_vector_tags) i = 0; i < _vector_tags.size(); i++, ++vector_tag)
254 : {
255 15446751 : const VectorTag & tag = _subproblem.getVectorTag(*vector_tag);
256 15446751 : _re_blocks[i] = &assembly.residualBlockNeighbor(ivar, Assembly::LocalDataKey{}, tag._type_id);
257 : }
258 15445455 : _local_re.resize(_re_blocks[0]->size());
259 :
260 15445455 : _absre_blocks.resize(_abs_vector_tags.size());
261 15445455 : vector_tag = _abs_vector_tags.begin();
262 15445583 : for (MooseIndex(_abs_vector_tags) i = 0; i < _abs_vector_tags.size(); i++, ++vector_tag)
263 : {
264 128 : const VectorTag & tag = _subproblem.getVectorTag(*vector_tag);
265 128 : _absre_blocks[i] =
266 256 : &assembly.residualBlockNeighbor(ivar, Assembly::LocalDataKey{}, tag._type_id);
267 : }
268 15445455 : }
269 :
270 : void
271 100442 : TaggingInterface::prepareVectorTagLower(Assembly & assembly, unsigned int ivar)
272 : {
273 100442 : _re_blocks.resize(_vector_tags.size());
274 : mooseAssert(_vector_tags.size() >= 1, "we need at least one active tag");
275 100442 : auto vector_tag = _vector_tags.begin();
276 200884 : for (MooseIndex(_vector_tags) i = 0; i < _vector_tags.size(); i++, ++vector_tag)
277 : {
278 100442 : const VectorTag & tag = _subproblem.getVectorTag(*vector_tag);
279 100442 : _re_blocks[i] = &assembly.residualBlockLower(ivar, Assembly::LocalDataKey{}, tag._type_id);
280 : }
281 100442 : _local_re.resize(_re_blocks[0]->size());
282 :
283 100442 : _absre_blocks.resize(_abs_vector_tags.size());
284 100442 : vector_tag = _abs_vector_tags.begin();
285 100570 : for (MooseIndex(_abs_vector_tags) i = 0; i < _abs_vector_tags.size(); i++, ++vector_tag)
286 : {
287 128 : const VectorTag & tag = _subproblem.getVectorTag(*vector_tag);
288 128 : _absre_blocks[i] = &assembly.residualBlockLower(ivar, Assembly::LocalDataKey{}, tag._type_id);
289 : }
290 100442 : }
291 :
292 : void
293 124078626 : TaggingInterface::prepareMatrixTag(Assembly & assembly, unsigned int ivar, unsigned int jvar)
294 : {
295 124078626 : _ke_blocks.resize(_matrix_tags.size());
296 : mooseAssert(_matrix_tags.size() >= 1, "we need at least one active tag");
297 124078626 : auto mat_vector = _matrix_tags.begin();
298 288655031 : for (MooseIndex(_matrix_tags) i = 0; i < _matrix_tags.size(); i++, ++mat_vector)
299 164576405 : _ke_blocks[i] = &assembly.jacobianBlock(ivar, jvar, Assembly::LocalDataKey{}, *mat_vector);
300 :
301 124078626 : _local_ke.resize(_ke_blocks[0]->m(), _ke_blocks[0]->n());
302 124078626 : }
303 :
304 : void
305 0 : TaggingInterface::prepareMatrixTag(Assembly & assembly,
306 : unsigned int ivar,
307 : unsigned int jvar,
308 : DenseMatrix<Number> & k) const
309 : {
310 : mooseAssert(!_matrix_tags.empty(), "No matrix tags exist");
311 : const auto & ij_mat =
312 0 : assembly.jacobianBlock(ivar, jvar, Assembly::LocalDataKey{}, *_matrix_tags.begin());
313 0 : k.resize(ij_mat.m(), ij_mat.n());
314 0 : }
315 :
316 : void
317 634 : TaggingInterface::prepareMatrixTagNonlocal(Assembly & assembly,
318 : unsigned int ivar,
319 : unsigned int jvar)
320 : {
321 634 : _ke_blocks.resize(_matrix_tags.size());
322 : mooseAssert(_matrix_tags.size() >= 1, "we need at least one active tag");
323 634 : auto mat_vector = _matrix_tags.begin();
324 1268 : for (MooseIndex(_matrix_tags) i = 0; i < _matrix_tags.size(); i++, ++mat_vector)
325 1268 : _ke_blocks[i] =
326 634 : &assembly.jacobianBlockNonlocal(ivar, jvar, Assembly::LocalDataKey{}, *mat_vector);
327 :
328 634 : _nonlocal_ke.resize(_ke_blocks[0]->m(), _ke_blocks[0]->n());
329 634 : }
330 :
331 : void
332 354153 : TaggingInterface::prepareMatrixTagNeighbor(Assembly & assembly,
333 : unsigned int ivar,
334 : unsigned int jvar,
335 : Moose::DGJacobianType type)
336 : {
337 354153 : _ke_blocks.resize(_matrix_tags.size());
338 : mooseAssert(_matrix_tags.size() >= 1, "we need at least one active tag");
339 354153 : auto mat_vector = _matrix_tags.begin();
340 720582 : for (MooseIndex(_matrix_tags) i = 0; i < _matrix_tags.size(); i++, ++mat_vector)
341 732858 : _ke_blocks[i] =
342 366429 : &assembly.jacobianBlockNeighbor(type, ivar, jvar, Assembly::LocalDataKey{}, *mat_vector);
343 :
344 354153 : _local_ke.resize(_ke_blocks[0]->m(), _ke_blocks[0]->n());
345 354153 : }
346 :
347 : void
348 3770 : TaggingInterface::prepareMatrixTagNeighbor(Assembly & assembly,
349 : unsigned int ivar,
350 : unsigned int jvar,
351 : Moose::DGJacobianType type,
352 : DenseMatrix<Number> & k) const
353 : {
354 : mooseAssert(!_matrix_tags.empty(), "No matrix tags exist");
355 3770 : const auto & ij_mat = assembly.jacobianBlockNeighbor(
356 3770 : type, ivar, jvar, Assembly::LocalDataKey{}, *_matrix_tags.begin());
357 3770 : k.resize(ij_mat.m(), ij_mat.n());
358 3770 : }
359 :
360 : void
361 276184 : TaggingInterface::prepareMatrixTagLower(Assembly & assembly,
362 : unsigned int ivar,
363 : unsigned int jvar,
364 : Moose::ConstraintJacobianType type)
365 : {
366 276184 : _ke_blocks.resize(_matrix_tags.size());
367 : mooseAssert(_matrix_tags.size() >= 1, "we need at least one active tag");
368 276184 : auto mat_vector = _matrix_tags.begin();
369 552368 : for (MooseIndex(_matrix_tags) i = 0; i < _matrix_tags.size(); i++, ++mat_vector)
370 552368 : _ke_blocks[i] =
371 276184 : &assembly.jacobianBlockMortar(type, ivar, jvar, Assembly::LocalDataKey{}, *mat_vector);
372 :
373 276184 : _local_ke.resize(_ke_blocks[0]->m(), _ke_blocks[0]->n());
374 276184 : }
375 :
376 : void
377 674475669 : TaggingInterface::accumulateTaggedLocalResidual()
378 : {
379 : #ifndef NDEBUG
380 : if (_subproblem.checkResidualForNans())
381 : checkForNans();
382 : #endif
383 :
384 1352729738 : for (auto & re : _re_blocks)
385 678254069 : *re += _local_re;
386 674935773 : for (auto & absre : _absre_blocks)
387 1380824 : for (const auto i : index_range(_local_re))
388 920720 : (*absre)(i) += std::abs(_local_re(i));
389 674475669 : }
390 :
391 : void
392 39499 : TaggingInterface::assignTaggedLocalResidual()
393 : {
394 : #ifndef NDEBUG
395 : if (_subproblem.checkResidualForNans())
396 : checkForNans();
397 : #endif
398 :
399 78998 : for (auto & re : _re_blocks)
400 39499 : *re = _local_re;
401 39509 : for (auto & absre : _absre_blocks)
402 20 : for (const auto i : index_range(_local_re))
403 10 : (*absre)(i) = std::abs(_local_re(i));
404 39499 : }
405 :
406 : void
407 124301679 : TaggingInterface::accumulateTaggedLocalMatrix()
408 : {
409 288980513 : for (auto & ke : _ke_blocks)
410 164678834 : *ke += _local_ke;
411 124301679 : }
412 :
413 : void
414 0 : TaggingInterface::accumulateTaggedLocalMatrix(Assembly & assembly,
415 : const unsigned int ivar,
416 : const unsigned int jvar,
417 : const DenseMatrix<Number> & k)
418 : {
419 0 : _ke_blocks.resize(_matrix_tags.size());
420 : mooseAssert(_matrix_tags.size() >= 1, "we need at least one active tag");
421 0 : auto mat_vector = _matrix_tags.begin();
422 0 : for (MooseIndex(_matrix_tags) i = 0; i < _matrix_tags.size(); i++, ++mat_vector)
423 0 : _ke_blocks[i] = &assembly.jacobianBlock(ivar, jvar, Assembly::LocalDataKey{}, *mat_vector);
424 : mooseAssert(_ke_blocks[0]->m() == k.m() && _ke_blocks[0]->n() == k.n(),
425 : "Passed-in k must match the blocks we are about to sum into");
426 0 : for (auto & ke : _ke_blocks)
427 0 : *ke += k;
428 0 : }
429 :
430 : void
431 0 : TaggingInterface::accumulateTaggedLocalMatrix(Assembly & assembly,
432 : const unsigned int ivar,
433 : const unsigned int jvar,
434 : const Moose::DGJacobianType type,
435 : const DenseMatrix<Number> & k)
436 : {
437 0 : _ke_blocks.resize(_matrix_tags.size());
438 : mooseAssert(_matrix_tags.size() >= 1, "we need at least one active tag");
439 0 : auto mat_vector = _matrix_tags.begin();
440 0 : for (MooseIndex(_matrix_tags) i = 0; i < _matrix_tags.size(); i++, ++mat_vector)
441 0 : _ke_blocks[i] =
442 0 : &assembly.jacobianBlockNeighbor(type, ivar, jvar, Assembly::LocalDataKey{}, *mat_vector);
443 : mooseAssert(_ke_blocks[0]->m() == k.m() && _ke_blocks[0]->n() == k.n(),
444 : "Passed-in k must match the blocks we are about to sum into");
445 0 : for (auto & ke : _ke_blocks)
446 0 : *ke += k;
447 0 : }
448 :
449 : void
450 634 : TaggingInterface::accumulateTaggedNonlocalMatrix()
451 : {
452 1268 : for (auto & ke : _ke_blocks)
453 634 : *ke += _nonlocal_ke;
454 634 : }
455 :
456 : void
457 10 : TaggingInterface::assignTaggedLocalMatrix()
458 : {
459 20 : for (auto & ke : _ke_blocks)
460 10 : *ke = _local_ke;
461 10 : }
462 :
463 : void
464 1024764 : TaggingInterface::addResiduals(Assembly & assembly, const ADResidualsPacket & packet)
465 : {
466 1024764 : addResiduals(assembly, packet.residuals, packet.dof_indices, packet.scaling_factor);
467 1024764 : }
468 :
469 : void
470 0 : TaggingInterface::addResidualsAndJacobian(Assembly & assembly, const ADResidualsPacket & packet)
471 : {
472 0 : addResidualsAndJacobian(assembly, packet.residuals, packet.dof_indices, packet.scaling_factor);
473 0 : }
474 :
475 : void
476 466824 : TaggingInterface::addJacobian(Assembly & assembly, const ADResidualsPacket & packet)
477 : {
478 466824 : addJacobian(assembly, packet.residuals, packet.dof_indices, packet.scaling_factor);
479 466824 : }
480 :
481 : #ifndef NDEBUG
482 : void
483 : TaggingInterface::checkForNans() const
484 : {
485 : for (const auto i : index_range(_local_re))
486 : if (!std::isfinite(_local_re(i)))
487 : {
488 : std::stringstream ss;
489 : ss << "NaN or Inf detected in '" << _moose_object.name() << "'.\n";
490 : ss << "To further troubleshoot this value in this residual object, add the following lines "
491 : "before returning the value in the computeQpResidual() (or similar) method in the "
492 : "source file for the class of '"
493 : << _moose_object.name() << "':\n\n";
494 : ss << " if (!std::isfinite(<return value>))\n";
495 : ss << " mooseError(\"Found NaN or Inf\");\n\n";
496 : ss << "Then you can use a breakpoint in a debugger to troubleshoot the origin of the NaN or "
497 : "Inf value.";
498 :
499 : mooseError(ss.str());
500 : }
501 : }
502 : #endif
503 :
504 575085 : TaggingInterface::~TaggingInterface() {}
|