https://mooseframework.inl.gov
DisplacedProblem.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 // MOOSE includes
11 
12 #include "AuxiliarySystem.h"
13 #include "FEProblem.h"
14 #include "MooseApp.h"
15 #include "MooseMesh.h"
16 #include "NonlinearSystem.h"
17 #include "Problem.h"
19 #include "SubProblem.h"
20 #include "AllNodesSendListThread.h"
21 #include "Assembly.h"
22 #include "DisplacedProblem.h"
23 #include "libmesh/numeric_vector.h"
24 #include "libmesh/fe_interface.h"
25 #include "libmesh/mesh_base.h"
26 #include "libmesh/transient_system.h"
27 #include "libmesh/explicit_system.h"
28 
29 using namespace libMesh;
30 
32 
35 {
37  params.addClassDescription(
38  "A Problem object for providing access to the displaced finite element "
39  "mesh and associated variables.");
40  params.addPrivateParam<MooseMesh *>("mesh");
41  params.addPrivateParam<std::vector<std::string>>("displacements", {});
42  return params;
43 }
44 
46  : SubProblem(parameters),
47  _mproblem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base")
48  ? *getParam<FEProblemBase *>("_fe_problem_base")
49  : *getParam<FEProblem *>("_fe_problem")),
50  _mesh(*getParam<MooseMesh *>("mesh")),
51  _eq(_mesh),
52  _ref_mesh(_mproblem.mesh()),
53  _displacements(getParam<std::vector<std::string>>("displacements")),
54  _geometric_search_data(*this, _mesh)
55 
56 {
57  // Disable refinement/coarsening in EquationSystems::reinit because we already do this ourselves
59 
60  // TODO: Move newAssemblyArray further up to SubProblem so that we can use it here
61  unsigned int n_threads = libMesh::n_threads();
62 
63  _assembly.resize(n_threads);
64  for (const auto nl_sys_num : make_range(_mproblem.numNonlinearSystems()))
65  {
66  _displaced_solver_systems.emplace_back(std::make_unique<DisplacedSystem>(
67  *this,
68  _mproblem,
70  "displaced_" + _mproblem.getNonlinearSystemBase(nl_sys_num).name() + "_" +
71  std::to_string(nl_sys_num),
73  auto & displaced_nl = _displaced_solver_systems.back();
74 
75  for (unsigned int i = 0; i < n_threads; ++i)
76  _assembly[i].emplace_back(std::make_unique<Assembly>(*displaced_nl, i));
77  }
78 
79  _nl_solution.resize(_displaced_solver_systems.size(), nullptr);
80 
82  std::make_unique<DisplacedSystem>(*this,
83  _mproblem,
85  "displaced_" + _mproblem.getAuxiliarySystem().name(),
87 
88  // // Generally speaking, the mesh is prepared for use, and consequently remote elements are deleted
89  // // well before our Problem(s) are constructed. Historically, in MooseMesh we have a bunch of
90  // // needs_prepare type flags that make it so we never call prepare_for_use (and consequently
91  // // delete_remote_elements) again. So the below line, historically, has had no impact. HOWEVER:
92  // // I've added some code in SetupMeshCompleteAction for deleting remote elements post
93  // // EquationSystems::init. If I execute that code without default ghosting, then I get > 40 MOOSE
94  // // test failures, so we clearly have some simulations that are not yet covered properly by
95  // // relationship managers. Until that is resolved, I am going to retain default geometric ghosting
96  // if (!_default_ghosting)
97  // _mesh.getMesh().remove_ghosting_functor(_mesh.getMesh().default_ghosting());
98 
100 
102 }
103 
105 
106 bool
108 {
109  return _mproblem.isTransient();
110 }
111 
112 std::set<dof_id_type> &
114 {
115  return _mproblem.ghostedElems();
116 }
117 
118 void
120  Order order,
121  Order volume_order,
122  Order face_order,
123  SubdomainID block,
124  const bool allow_negative_qweights)
125 {
126  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
127  for (const auto sys_num : index_range(_assembly[tid]))
128  _assembly[tid][sys_num]->createQRules(
129  type, order, volume_order, face_order, block, allow_negative_qweights);
130 }
131 
132 void
134 {
135  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
136  for (const auto nl_sys_num : index_range(_assembly[tid]))
137  _assembly[tid][nl_sys_num]->bumpVolumeQRuleOrder(order, block);
138 }
139 
140 void
142 {
143  for (unsigned int tid = 0; tid < libMesh::n_threads(); ++tid)
144  for (const auto nl_sys_num : index_range(_assembly[tid]))
145  _assembly[tid][nl_sys_num]->bumpAllQRuleOrder(order, block);
146 }
147 
148 void
150 {
151  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
152  {
153  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
154  _assembly[tid][nl_sys_num]->init(_mproblem.couplingMatrix(nl_sys_num));
155 
156  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
157  {
158  std::vector<std::pair<unsigned int, unsigned short>> disp_numbers_and_directions;
159  for (const auto direction : index_range(_displacements))
160  {
161  const auto & disp_string = _displacements[direction];
162  const auto & disp_variable = getVariable(tid, disp_string);
163  if (disp_variable.sys().number() == nl_sys_num)
164  disp_numbers_and_directions.push_back(
165  std::make_pair(disp_variable.number(), cast_int<unsigned short>(direction)));
166  }
167  _assembly[tid][nl_sys_num]->assignDisplacements(std::move(disp_numbers_and_directions));
168  }
169  }
170 
171  for (auto & nl : _displaced_solver_systems)
172  {
173  nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
174  nl->preInit();
175  }
176 
177  _displaced_aux->dofMap().attach_extra_send_list_function(&extraSendList, _displaced_aux.get());
178  _displaced_aux->preInit();
179 
180  {
181  TIME_SECTION("eq::init", 2, "Initializing Displaced Equation System");
182  _eq.init();
183  }
184 
185  for (auto & nl : _displaced_solver_systems)
186  nl->postInit();
187  _displaced_aux->postInit();
188 
189  _mesh.meshChanged();
190 
191  if (haveFV())
193 }
194 
195 void
197 {
198 }
199 
200 void
202 {
203  for (const auto nl_sys_num : make_range(_mproblem.numNonlinearSystems()))
204  _displaced_solver_systems[nl_sys_num]->copyTimeIntegrators(
205  _mproblem.getNonlinearSystemBase(nl_sys_num));
206  _displaced_aux->copyTimeIntegrators(_mproblem.getAuxiliarySystem());
207 }
208 
209 void
211 {
212  for (auto & displaced_nl : _displaced_solver_systems)
213  displaced_nl->saveOldSolutions();
214  _displaced_aux->saveOldSolutions();
215 }
216 
217 void
219 {
220  for (auto & displaced_nl : _displaced_solver_systems)
221  displaced_nl->restoreOldSolutions();
222  _displaced_aux->restoreOldSolutions();
223 }
224 
225 void
227 {
228  (*_displaced_aux->sys().solution) = aux_soln;
229  _displaced_aux->update();
230 }
231 
232 void
234 {
235  TIME_SECTION("syncSolutions", 5, "Syncing Displaced Solutions");
236 
237  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
238  {
239  auto & displaced_nl = _displaced_solver_systems[nl_sys_num];
240  mooseAssert(nl_sys_num == displaced_nl->number(),
241  "We should have designed things such that the nl system numbers make their system "
242  "numbering in the EquationSystems object");
243  (*displaced_nl->sys().solution) =
244  *_mproblem.getNonlinearSystemBase(displaced_nl->number()).currentSolution();
245  displaced_nl->update();
246  }
248 }
249 
250 void
252  const std::map<unsigned int, const NumericVector<Number> *> & nl_solns,
253  const NumericVector<Number> & aux_soln)
254 {
255  TIME_SECTION("syncSolutions", 5, "Syncing Displaced Solutions");
256 
257  for (const auto [nl_sys_num, nl_soln] : nl_solns)
258  {
259  (*_displaced_solver_systems[nl_sys_num]->sys().solution) = *nl_soln;
260  _displaced_solver_systems[nl_sys_num]->update();
261  }
262  syncAuxSolution(aux_soln);
263 }
264 
265 void
266 DisplacedProblem::updateMesh(bool mesh_changing)
267 {
268  TIME_SECTION("updateMesh", 3, "Updating Displaced Mesh");
269 
270  // If the mesh is changing, we are probably performing adaptivity. In that case, we do *not* want
271  // to use the undisplaced mesh solution because it may be out-of-sync, whereas our displaced mesh
272  // solution should be in the correct state after getting restricted/prolonged in
273  // EquationSystems::reinit (must have been called before this method)
274  if (!mesh_changing)
275  syncSolutions();
276 
277  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
278  _nl_solution[nl_sys_num] = _displaced_solver_systems[nl_sys_num]->sys().solution.get();
279  _aux_solution = _displaced_aux->sys().solution.get();
280 
281  // If the displaced mesh has been serialized to one processor (as
282  // may have occurred if it was used for Exodus output), then we need
283  // the reference mesh to be also. For that matter, did anyone
284  // somehow serialize the whole mesh? Hopefully not but let's avoid
285  // causing errors if so.
286  if (_mesh.getMesh().is_serial() && !this->refMesh().getMesh().is_serial())
287  this->refMesh().getMesh().allgather();
288 
290  this->refMesh().getMesh().gather_to_zero();
291 
293 
294  // We displace all nodes, not just semilocal nodes, because
295  // parallel-inconsistent mesh geometry makes libMesh cry.
296  NodeRange node_range(_mesh.getMesh().nodes_begin(),
297  _mesh.getMesh().nodes_end(),
298  /*grainsize=*/1);
299 
300  Threads::parallel_reduce(node_range, udmt);
301  // Displacement of the mesh has invalidated the point locator data (e.g. bounding boxes)
303 
304  // The mesh has changed. Face information normals, areas, etc. must be re-calculated
305  if (haveFV())
307 
308  // Update the geometric searches that depend on the displaced mesh. This call can end up running
309  // NearestNodeThread::operator() which has a throw inside of it. We need to catch it and make sure
310  // it's propagated to all processes before updating the point locator because the latter requires
311  // communication
312  try
313  {
314  // We may need to re-run geometric operations like SecondaryNeighborhoodTread if, for instance,
315  // we have performed mesh adaptivity
316  if (mesh_changing)
318  else
320  }
321  catch (MooseException & e)
322  {
324  }
325 
326  if (udmt.hasDisplacement())
328 
329  // The below call will throw an exception on all processes if any of our processes had an
330  // exception above. This exception will be caught higher up the call stack and the error message
331  // will be printed there
332  _mproblem.checkExceptionAndStopSolve(/*print_message=*/false);
333 
334  // Since the Mesh changed, update the PointLocator object used by DiracKernels.
336 }
337 
338 void
339 DisplacedProblem::updateMesh(const std::map<unsigned int, const NumericVector<Number> *> & nl_solns,
340  const NumericVector<Number> & aux_soln)
341 {
342  TIME_SECTION("updateMesh", 3, "Updating Displaced Mesh");
343 
344  syncSolutions(nl_solns, aux_soln);
345 
346  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
347  _nl_solution[nl_sys_num] = _displaced_solver_systems[nl_sys_num]->sys().solution.get();
348  _aux_solution = _displaced_aux->sys().solution.get();
349 
351 
352  // We displace all nodes, not just semilocal nodes, because
353  // parallel-inconsistent mesh geometry makes libMesh cry.
354  NodeRange node_range(_mesh.getMesh().nodes_begin(),
355  _mesh.getMesh().nodes_end(),
356  /*grainsize=*/1);
357 
358  Threads::parallel_reduce(node_range, udmt);
359 
360  // Update the geometric searches that depend on the displaced mesh. This call can end up running
361  // NearestNodeThread::operator() which has a throw inside of it. We need to catch it and make sure
362  // it's propagated to all processes before updating the point locator because the latter requires
363  // communication
364  try
365  {
367  }
368  catch (MooseException & e)
369  {
371  }
372 
373  if (udmt.hasDisplacement())
375 
376  // The below call will throw an exception on all processes if any of our processes had an
377  // exception above. This exception will be caught higher up the call stack and the error message
378  // will be printed there
379  _mproblem.checkExceptionAndStopSolve(/*print_message=*/false);
380 
381  // Since the Mesh changed, update the PointLocator object used by DiracKernels.
383 }
384 
385 TagID
386 DisplacedProblem::addVectorTag(const TagName & tag_name,
387  const Moose::VectorTagType type /* = Moose::VECTOR_TAG_RESIDUAL */)
388 {
389  return _mproblem.addVectorTag(tag_name, type);
390 }
391 
392 const VectorTag &
394 {
395  return _mproblem.getVectorTag(tag_id);
396 }
397 
398 TagID
399 DisplacedProblem::getVectorTagID(const TagName & tag_name) const
400 {
401  return _mproblem.getVectorTagID(tag_name);
402 }
403 
404 TagName
406 {
407  return _mproblem.vectorTagName(tag_id);
408 }
409 
410 bool
412 {
413  return _mproblem.vectorTagExists(tag_id);
414 }
415 
416 bool
417 DisplacedProblem::vectorTagExists(const TagName & tag_name) const
418 {
419  return _mproblem.vectorTagExists(tag_name);
420 }
421 
422 unsigned int
423 DisplacedProblem::numVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
424 {
425  return _mproblem.numVectorTags(type);
426 }
427 
428 const std::vector<VectorTag> &
429 DisplacedProblem::getVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
430 {
431  return _mproblem.getVectorTags(type);
432 }
433 
436 {
437  return _mproblem.vectorTagType(tag_id);
438 }
439 
440 TagID
442 {
443  return _mproblem.addMatrixTag(tag_name);
444 }
445 
446 TagID
447 DisplacedProblem::getMatrixTagID(const TagName & tag_name) const
448 {
449  return _mproblem.getMatrixTagID(tag_name);
450 }
451 
452 TagName
454 {
455  return _mproblem.matrixTagName(tag);
456 }
457 
458 bool
459 DisplacedProblem::matrixTagExists(const TagName & tag_name) const
460 {
461  return _mproblem.matrixTagExists(tag_name);
462 }
463 
464 bool
466 {
467  return _mproblem.matrixTagExists(tag_id);
468 }
469 
470 unsigned int
472 {
473  return _mproblem.numMatrixTags();
474 }
475 
476 bool
477 DisplacedProblem::hasVariable(const std::string & var_name) const
478 {
479  for (auto & nl : _displaced_solver_systems)
480  if (nl->hasVariable(var_name))
481  return true;
482  if (_displaced_aux->hasVariable(var_name))
483  return true;
484 
485  return false;
486 }
487 
490  const std::string & var_name,
491  Moose::VarKindType expected_var_type,
492  Moose::VarFieldType expected_var_field_type) const
493 {
494  return getVariableHelper(tid,
495  var_name,
496  expected_var_type,
497  expected_var_field_type,
499  *_displaced_aux);
500 }
501 
503 DisplacedProblem::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
504 {
505  for (auto & nl : _displaced_solver_systems)
506  if (nl->hasVariable(var_name))
507  return nl->getFieldVariable<Real>(tid, var_name);
508  if (_displaced_aux->hasVariable(var_name))
509  return _displaced_aux->getFieldVariable<Real>(tid, var_name);
510 
511  mooseError("No variable with name '" + var_name + "'");
512 }
513 
515 DisplacedProblem::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
516 {
517  for (auto & nl : _displaced_solver_systems)
518  if (nl->hasVariable(var_name))
519  return nl->getActualFieldVariable<Real>(tid, var_name);
520  if (_displaced_aux->hasVariable(var_name))
521  return _displaced_aux->getActualFieldVariable<Real>(tid, var_name);
522 
523  mooseError("No variable with name '" + var_name + "'");
524 }
525 
527 DisplacedProblem::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
528 {
529  for (auto & nl : _displaced_solver_systems)
530  if (nl->hasVariable(var_name))
531  return nl->getFieldVariable<RealVectorValue>(tid, var_name);
532  if (_displaced_aux->hasVariable(var_name))
533  return _displaced_aux->getFieldVariable<RealVectorValue>(tid, var_name);
534 
535  mooseError("No variable with name '" + var_name + "'");
536 }
537 
539 DisplacedProblem::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
540 {
541  for (auto & nl : _displaced_solver_systems)
542  if (nl->hasVariable(var_name))
543  return nl->getFieldVariable<RealEigenVector>(tid, var_name);
544  if (_displaced_aux->hasVariable(var_name))
545  return _displaced_aux->getFieldVariable<RealEigenVector>(tid, var_name);
546 
547  mooseError("No variable with name '" + var_name + "'");
548 }
549 
550 bool
551 DisplacedProblem::hasScalarVariable(const std::string & var_name) const
552 {
553  for (auto & nl : _displaced_solver_systems)
554  if (nl->hasScalarVariable(var_name))
555  return true;
556  if (_displaced_aux->hasScalarVariable(var_name))
557  return true;
558 
559  return false;
560 }
561 
563 DisplacedProblem::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
564 {
565  for (auto & nl : _displaced_solver_systems)
566  if (nl->hasScalarVariable(var_name))
567  return nl->getScalarVariable(tid, var_name);
568  if (_displaced_aux->hasScalarVariable(var_name))
569  return _displaced_aux->getScalarVariable(tid, var_name);
570 
571  mooseError("No variable with name '" + var_name + "'");
572 }
573 
574 System &
575 DisplacedProblem::getSystem(const std::string & var_name)
576 {
577  for (const auto sys_num : make_range(_eq.n_systems()))
578  {
579  auto & sys = _eq.get_system(sys_num);
580  if (sys.has_variable(var_name))
581  return sys;
582  }
583 
584  mooseError("Unable to find a system containing the variable " + var_name);
585 }
586 
587 void
588 DisplacedProblem::addVariable(const std::string & var_type,
589  const std::string & name,
590  InputParameters & parameters,
591  const unsigned int nl_system_number)
592 {
593  _displaced_solver_systems[nl_system_number]->addVariable(var_type, name, parameters);
594 }
595 
596 void
597 DisplacedProblem::addAuxVariable(const std::string & var_type,
598  const std::string & name,
599  InputParameters & parameters)
600 {
601  _displaced_aux->addVariable(var_type, name, parameters);
602 }
603 
604 unsigned int
606 {
607  return _mproblem.currentNlSysNum();
608 }
609 
610 unsigned int
612 {
614 }
615 
616 void
617 DisplacedProblem::prepare(const Elem * elem, const THREAD_ID tid)
618 {
619  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
620  {
621  _assembly[tid][nl_sys_num]->reinit(elem);
622  _displaced_solver_systems[nl_sys_num]->prepare(tid);
623  // This method is called outside of residual/Jacobian callbacks during initial condition
624  // evaluation
626  _assembly[tid][nl_sys_num]->prepareJacobianBlock();
627  _assembly[tid][nl_sys_num]->prepareResidual();
628  }
629 
630  _displaced_aux->prepare(tid);
631 }
632 
633 void
635 {
636  _assembly[tid][currentNlSysNum()]->prepareNonlocal();
637 }
638 
639 void
640 DisplacedProblem::prepareFace(const Elem * /*elem*/, const THREAD_ID tid)
641 {
642  for (auto & nl : _displaced_solver_systems)
643  nl->prepareFace(tid, true);
644  _displaced_aux->prepareFace(tid, false);
645 }
646 
647 void
648 DisplacedProblem::prepare(const Elem * elem,
649  unsigned int ivar,
650  unsigned int jvar,
651  const std::vector<dof_id_type> & dof_indices,
652  const THREAD_ID tid)
653 {
654  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
655  {
656  _assembly[tid][nl_sys_num]->reinit(elem);
657  _displaced_solver_systems[nl_sys_num]->prepare(tid);
658  }
659  _displaced_aux->prepare(tid);
660  _assembly[tid][currentNlSysNum()]->prepareBlock(ivar, jvar, dof_indices);
661 }
662 
663 void
665 {
666  SubdomainID did = elem->subdomain_id();
667  for (auto & assembly : _assembly[tid])
669 }
670 
671 void
672 DisplacedProblem::setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid)
673 {
674  SubdomainID did = elem->neighbor_ptr(side)->subdomain_id();
675  for (auto & assembly : _assembly[tid])
677 }
678 
679 void
681  unsigned int jvar,
682  const std::vector<dof_id_type> & idof_indices,
683  const std::vector<dof_id_type> & jdof_indices,
684  const THREAD_ID tid)
685 {
686  _assembly[tid][currentNlSysNum()]->prepareBlockNonlocal(ivar, jvar, idof_indices, jdof_indices);
687 }
688 
689 void
691 {
692  _assembly[tid][currentNlSysNum()]->prepare();
693 }
694 
695 void
697 {
698  _assembly[tid][currentNlSysNum()]->prepareNeighbor();
699 }
700 
701 bool
703 {
704  std::vector<Point> & points = _dirac_kernel_info.getPoints()[elem].first;
705 
706  unsigned int n_points = points.size();
707 
708  if (n_points)
709  {
710  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
711  {
712  _assembly[tid][nl_sys_num]->reinitAtPhysical(elem, points);
713  _displaced_solver_systems[nl_sys_num]->prepare(tid);
714  }
715  _displaced_aux->prepare(tid);
716 
717  reinitElem(elem, tid);
718  }
719 
720  _assembly[tid][currentNlSysNum()]->prepare();
721 
722  return n_points > 0;
723 }
724 
725 void
727 {
728  for (auto & nl : _displaced_solver_systems)
729  nl->reinitElem(elem, tid);
730  _displaced_aux->reinitElem(elem, tid);
731 }
732 
733 void
735  const std::vector<Point> & phys_points_in_elem,
736  const THREAD_ID tid)
737 {
738  mooseAssert(_mesh.queryElemPtr(elem->id()) == elem,
739  "Are you calling this method with a undisplaced mesh element?");
740 
741  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
742  {
743  _assembly[tid][nl_sys_num]->reinitAtPhysical(elem, phys_points_in_elem);
744  _displaced_solver_systems[nl_sys_num]->prepare(tid);
745  _assembly[tid][nl_sys_num]->prepare();
746  }
747  _displaced_aux->prepare(tid);
748 
749  reinitElem(elem, tid);
750 }
751 
752 void
753 DisplacedProblem::reinitElemFace(const Elem * elem, unsigned int side, const THREAD_ID tid)
754 {
755  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
756  {
757  _assembly[tid][nl_sys_num]->reinit(elem, side);
758  _displaced_solver_systems[nl_sys_num]->reinitElemFace(elem, side, tid);
759  }
760  _displaced_aux->reinitElemFace(elem, side, tid);
761 }
762 
763 void
765 {
766  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
767  {
768  _assembly[tid][nl_sys_num]->reinit(node);
769  _displaced_solver_systems[nl_sys_num]->reinitNode(node, tid);
770  }
771  _displaced_aux->reinitNode(node, tid);
772 }
773 
774 void
776 {
777  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
778  {
779  _assembly[tid][nl_sys_num]->reinit(node);
780  _displaced_solver_systems[nl_sys_num]->reinitNodeFace(node, bnd_id, tid);
781  }
782  _displaced_aux->reinitNodeFace(node, bnd_id, tid);
783 }
784 
785 void
786 DisplacedProblem::reinitNodes(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
787 {
788  for (auto & nl : _displaced_solver_systems)
789  nl->reinitNodes(nodes, tid);
790  _displaced_aux->reinitNodes(nodes, tid);
791 }
792 
793 void
794 DisplacedProblem::reinitNodesNeighbor(const std::vector<dof_id_type> & nodes, const THREAD_ID tid)
795 {
796  for (auto & nl : _displaced_solver_systems)
797  nl->reinitNodesNeighbor(nodes, tid);
798  _displaced_aux->reinitNodesNeighbor(nodes, tid);
799 }
800 
801 void
802 DisplacedProblem::reinitNeighbor(const Elem * elem, unsigned int side, const THREAD_ID tid)
803 {
804  reinitNeighbor(elem, side, tid, nullptr);
805 }
806 
807 void
809  unsigned int side,
810  const THREAD_ID tid,
811  const std::vector<Point> * neighbor_reference_points)
812 {
813  setNeighborSubdomainID(elem, side, tid);
814 
815  const Elem * neighbor = elem->neighbor_ptr(side);
816  unsigned int neighbor_side = neighbor->which_neighbor_am_i(elem);
817 
818  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
819  {
820  _assembly[tid][nl_sys_num]->reinitElemAndNeighbor(
821  elem, side, neighbor, neighbor_side, neighbor_reference_points);
822  _displaced_solver_systems[nl_sys_num]->prepareNeighbor(tid);
823  // Called during stateful material property evaluation outside of solve
824  _assembly[tid][nl_sys_num]->prepareNeighbor();
825  }
826  _displaced_aux->prepareNeighbor(tid);
827 
828  for (auto & nl : _displaced_solver_systems)
829  {
830  nl->reinitElemFace(elem, side, tid);
831  nl->reinitNeighborFace(neighbor, neighbor_side, tid);
832  }
833  _displaced_aux->reinitElemFace(elem, side, tid);
834  _displaced_aux->reinitNeighborFace(neighbor, neighbor_side, tid);
835 }
836 
837 void
839  unsigned int neighbor_side,
840  const std::vector<Point> & physical_points,
841  const THREAD_ID tid)
842 {
843  mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
844  "Are you calling this method with a undisplaced mesh element?");
845 
846  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
847  {
848  // Reinit shape functions
849  _assembly[tid][nl_sys_num]->reinitNeighborAtPhysical(neighbor, neighbor_side, physical_points);
850 
851  // Set the neighbor dof indices
852  _displaced_solver_systems[nl_sys_num]->prepareNeighbor(tid);
853  }
854  _displaced_aux->prepareNeighbor(tid);
855 
857 
858  // Compute values at the points
859  for (auto & nl : _displaced_solver_systems)
860  nl->reinitNeighborFace(neighbor, neighbor_side, tid);
861  _displaced_aux->reinitNeighborFace(neighbor, neighbor_side, tid);
862 }
863 
864 void
866  const std::vector<Point> & physical_points,
867  const THREAD_ID tid)
868 {
869  mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
870  "Are you calling this method with a undisplaced mesh element?");
871 
872  for (const auto nl_sys_num : index_range(_displaced_solver_systems))
873  {
874  // Reinit shape functions
875  _assembly[tid][nl_sys_num]->reinitNeighborAtPhysical(neighbor, physical_points);
876 
877  // Set the neighbor dof indices
878  _displaced_solver_systems[nl_sys_num]->prepareNeighbor(tid);
879  }
880  _displaced_aux->prepareNeighbor(tid);
881 
883 
884  // Compute values at the points
885  for (auto & nl : _displaced_solver_systems)
886  nl->reinitNeighbor(neighbor, tid);
887  _displaced_aux->reinitNeighbor(neighbor, tid);
888 }
889 
890 void
892  unsigned int side,
893  const THREAD_ID tid)
894 {
895  reinitNeighbor(elem, side, tid);
896 
897  const Elem * lower_d_elem = _mesh.getLowerDElem(elem, side);
898  if (lower_d_elem && _mesh.interiorLowerDBlocks().count(lower_d_elem->subdomain_id()) > 0)
899  reinitLowerDElem(lower_d_elem, tid);
900  else
901  {
902  // with mesh refinement, lower-dimensional element might be defined on neighbor side
903  auto & neighbor = _assembly[tid][currentNlSysNum()]->neighbor();
904  auto & neighbor_side = _assembly[tid][currentNlSysNum()]->neighborSide();
905  const Elem * lower_d_elem_neighbor = _mesh.getLowerDElem(neighbor, neighbor_side);
906  if (lower_d_elem_neighbor &&
907  _mesh.interiorLowerDBlocks().count(lower_d_elem_neighbor->subdomain_id()) > 0)
908  {
909  auto qps = _assembly[tid][currentNlSysNum()]->qPointsFaceNeighbor().stdVector();
910  std::vector<Point> reference_points;
911  FEMap::inverse_map(
912  lower_d_elem_neighbor->dim(), lower_d_elem_neighbor, qps, reference_points);
913  reinitLowerDElem(lower_d_elem_neighbor, tid, &qps);
914  }
915  }
916 }
917 
918 void
920  bool reinit_for_derivative_reordering /*=false*/)
921 {
922  for (auto & nl : _displaced_solver_systems)
923  nl->reinitScalars(tid, reinit_for_derivative_reordering);
924  _displaced_aux->reinitScalars(tid, reinit_for_derivative_reordering);
925 }
926 
927 void
929 {
930  _assembly[tid][currentNlSysNum()]->prepareOffDiagScalar();
931 }
932 
933 void
934 DisplacedProblem::getDiracElements(std::set<const Elem *> & elems)
935 {
937 }
938 
939 void
941 {
943 }
944 
945 void
947 {
948  _assembly[tid][currentNlSysNum()]->addResidual(Assembly::GlobalDataKey{},
950 }
951 
952 void
954 {
955  _assembly[tid][currentNlSysNum()]->addResidualNeighbor(Assembly::GlobalDataKey{},
957 }
958 
959 void
961 {
962  _assembly[tid][currentNlSysNum()]->addResidualLower(Assembly::GlobalDataKey{},
964 }
965 
966 void
968 {
969  if (_displaced_solver_systems[currentNlSysNum()]->hasVector(
970  _displaced_solver_systems[currentNlSysNum()]->timeVectorTag()))
971  _assembly[tid][currentNlSysNum()]->addCachedResidualDirectly(
972  residual,
975 
976  if (_displaced_solver_systems[currentNlSysNum()]->hasVector(
977  _displaced_solver_systems[currentNlSysNum()]->nonTimeVectorTag()))
978  _assembly[tid][currentNlSysNum()]->addCachedResidualDirectly(
979  residual,
981  getVectorTag(_displaced_solver_systems[currentNlSysNum()]->nonTimeVectorTag()));
982 
983  std::vector<VectorTag> extra_residual_vector_tags;
984  extra_residual_vector_tags.reserve(currentResidualVectorTags().size());
985  const auto time_tag = _displaced_solver_systems[currentNlSysNum()]->timeVectorTag();
986  const auto non_time_tag = _displaced_solver_systems[currentNlSysNum()]->nonTimeVectorTag();
987  for (const auto & vector_tag : currentResidualVectorTags())
988  if (vector_tag._id != time_tag && vector_tag._id != non_time_tag)
989  extra_residual_vector_tags.push_back(vector_tag);
990 
991  // Flush extra vector tag caches (e.g. from extra_vector_tags on NodalConstraints)
992  // to their respective system vectors after the standard TIME/NONTIME caches above.
993  // Without this, NodalConstraint contributions to extra vector tags are silently
994  // discarded by the blanket clearCachedResiduals.
995  _assembly[tid][currentNlSysNum()]->addCachedResiduals(Assembly::GlobalDataKey{},
996  extra_residual_vector_tags);
997 
998  // We do this because by adding the cached residual directly, we cannot ensure that all of the
999  // cached residuals are emptied after only the two add calls above
1000  _assembly[tid][currentNlSysNum()]->clearCachedResiduals(Assembly::GlobalDataKey{});
1001 }
1002 
1003 void
1005 {
1006  _assembly[tid][currentNlSysNum()]->setResidual(
1007  residual,
1009  getVectorTag(_displaced_solver_systems[currentNlSysNum()]->residualVectorTag()));
1010 }
1011 
1012 void
1014 {
1015  _assembly[tid][currentNlSysNum()]->setResidualNeighbor(
1016  residual,
1018  getVectorTag(_displaced_solver_systems[currentNlSysNum()]->residualVectorTag()));
1019 }
1020 
1021 void
1023 {
1024  _assembly[tid][currentNlSysNum()]->addJacobian(Assembly::GlobalDataKey{});
1025 }
1026 
1027 void
1029 {
1030  _assembly[tid][currentNlSysNum()]->addJacobianNonlocal(Assembly::GlobalDataKey{});
1031 }
1032 
1033 void
1035 {
1036  _assembly[tid][currentNlSysNum()]->addJacobianNeighbor(Assembly::GlobalDataKey{});
1037 }
1038 
1039 void
1041 {
1042  _assembly[tid][currentNlSysNum()]->addJacobianNeighborLowerD(Assembly::GlobalDataKey{});
1043 }
1044 
1045 void
1047 {
1048  _assembly[tid][currentNlSysNum()]->addJacobianLowerD(Assembly::GlobalDataKey{});
1049 }
1050 
1051 void
1053 {
1054  _assembly[tid][currentNlSysNum()]->cacheJacobianNonlocal(Assembly::GlobalDataKey{});
1055 }
1056 
1057 void
1059  unsigned int ivar,
1060  unsigned int jvar,
1061  const DofMap & dof_map,
1062  std::vector<dof_id_type> & dof_indices,
1063  const std::set<TagID> & tags,
1064  const THREAD_ID tid)
1065 {
1066  _assembly[tid][currentNlSysNum()]->addJacobianBlockTags(
1067  jacobian, ivar, jvar, dof_map, dof_indices, Assembly::GlobalDataKey{}, tags);
1068 }
1069 
1070 void
1072  unsigned int ivar,
1073  unsigned int jvar,
1074  const DofMap & dof_map,
1075  const std::vector<dof_id_type> & idof_indices,
1076  const std::vector<dof_id_type> & jdof_indices,
1077  const std::set<TagID> & tags,
1078  const THREAD_ID tid)
1079 {
1080  _assembly[tid][currentNlSysNum()]->addJacobianBlockNonlocalTags(
1081  jacobian, ivar, jvar, dof_map, idof_indices, jdof_indices, Assembly::GlobalDataKey{}, tags);
1082 }
1083 
1084 void
1086  unsigned int ivar,
1087  unsigned int jvar,
1088  const DofMap & dof_map,
1089  std::vector<dof_id_type> & dof_indices,
1090  std::vector<dof_id_type> & neighbor_dof_indices,
1091  const std::set<TagID> & tags,
1092  const THREAD_ID tid)
1093 {
1094  _assembly[tid][currentNlSysNum()]->addJacobianNeighborTags(jacobian,
1095  ivar,
1096  jvar,
1097  dof_map,
1098  dof_indices,
1099  neighbor_dof_indices,
1101  tags);
1102 }
1103 
1104 void
1105 DisplacedProblem::prepareShapes(unsigned int var, const THREAD_ID tid)
1106 {
1107  _assembly[tid][currentNlSysNum()]->copyShapes(var);
1108 }
1109 
1110 void
1112 {
1113  _assembly[tid][currentNlSysNum()]->copyFaceShapes(var);
1114 }
1115 
1116 void
1118 {
1119  _assembly[tid][currentNlSysNum()]->copyNeighborShapes(var);
1120 }
1121 
1122 void
1124 {
1125  TIME_SECTION("updateGeometricSearch", 3, "Updating Displaced GeometricSearch");
1126 
1128 }
1129 
1130 void
1131 DisplacedProblem::meshChanged(const bool contract_mesh, const bool clean_refinement_flags)
1132 {
1133  // The mesh changed. The displaced equations system object only holds Systems, so calling
1134  // EquationSystems::reinit only prolongs/restricts the solution vectors, which is something that
1135  // needs to happen for every step of mesh adaptivity.
1136  _eq.reinit();
1137  if (contract_mesh)
1138  // Once vectors are restricted, we can delete children of coarsened elements
1139  _mesh.getMesh().contract();
1140  if (clean_refinement_flags)
1141  {
1142  // Finally clean refinement flags so that if someone tries to project vectors again without
1143  // an intervening mesh refinement to clean flags they won't run into trouble
1144  MeshRefinement refinement(_mesh.getMesh());
1145  refinement.clean_refinement_flags();
1146  }
1147 
1148  // Since the mesh has changed, we need to make sure that we update any of our
1149  // MOOSE-system specific data.
1150  for (auto & nl : _displaced_solver_systems)
1151  nl->reinit();
1152  _displaced_aux->reinit();
1153 
1154  // We've performed some mesh adaptivity. We need to
1155  // clear any quadrature nodes such that when we build the boundary node lists in
1156  // MooseMesh::meshChanged we don't have any extraneous extra boundary nodes lying around
1158 
1159  _mesh.meshChanged();
1160 
1161  // Before performing mesh adaptivity we un-displaced the mesh. We need to re-displace the mesh and
1162  // then reinitialize GeometricSearchData such that we have all the correct geometric information
1163  // for the changed mesh
1164  updateMesh(/*mesh_changing=*/true);
1165 }
1166 
1167 void
1169 {
1170  _mproblem.addGhostedElem(elem_id);
1171 }
1172 
1173 void
1175 {
1176  _mproblem.addGhostedBoundary(boundary_id);
1177 }
1178 
1179 void
1181 {
1183 }
1184 
1185 MooseMesh &
1187 {
1188  return _ref_mesh;
1189 }
1190 
1191 bool
1192 DisplacedProblem::solverSystemConverged(const unsigned int sys_num)
1193 {
1194  return _mproblem.converged(sys_num);
1195 }
1196 
1197 bool
1198 DisplacedProblem::computingPreSMOResidual(const unsigned int nl_sys_num) const
1199 {
1200  return _mproblem.computingPreSMOResidual(nl_sys_num);
1201 }
1202 
1203 void
1205 {
1206 }
1207 
1208 void
1210 {
1211 }
1212 
1213 void
1215 {
1216  // If undisplaceMesh() is called during initial adaptivity, it is
1217  // not valid to call _mesh.getActiveSemiLocalNodeRange() since it is
1218  // not set up yet. So we are creating the Range by hand.
1219  //
1220  // We must undisplace *all* our nodes to the _ref_mesh
1221  // configuration, not just the local ones, since the partitioners
1222  // require this. We are using the GRAIN_SIZE=1 from MooseMesh.C,
1223  // not sure how this value was decided upon.
1224  //
1225  // (DRG: The grainsize parameter is ultimately passed to TBB to help
1226  // it choose how to split up the range. A grainsize of 1 says "split
1227  // it as much as you want". Years ago I experimentally found that it
1228  // didn't matter much and that using 1 was fine.)
1229  //
1230  // Note: we don't have to invalidate/update as much stuff as
1231  // DisplacedProblem::updateMesh() does, since this will be handled
1232  // by a later call to updateMesh().
1233  NodeRange node_range(_mesh.getMesh().nodes_begin(),
1234  _mesh.getMesh().nodes_end(),
1235  /*grainsize=*/1);
1236 
1237  ResetDisplacedMeshThread rdmt(_mproblem, *this);
1238 
1239  // Undisplace the mesh using threads.
1240  Threads::parallel_reduce(node_range, rdmt);
1241 }
1242 
1243 LineSearch *
1245 {
1246  return _mproblem.getLineSearch();
1247 }
1248 
1249 const CouplingMatrix *
1250 DisplacedProblem::couplingMatrix(const unsigned int nl_sys_num) const
1251 {
1252  return _mproblem.couplingMatrix(nl_sys_num);
1253 }
1254 
1255 bool
1257 {
1259 }
1260 
1261 bool
1263 {
1265 }
1266 
1267 void
1269 {
1271 
1272  for (auto & nl : _displaced_solver_systems)
1273  nl->initialSetup();
1274  _displaced_aux->initialSetup();
1275 }
1276 
1277 void
1279 {
1281 
1282  for (auto & nl : _displaced_solver_systems)
1283  nl->timestepSetup();
1284  _displaced_aux->timestepSetup();
1285 }
1286 
1287 void
1289 {
1290  SubProblem::customSetup(exec_type);
1291 
1292  for (auto & nl : _displaced_solver_systems)
1293  nl->customSetup(exec_type);
1294  _displaced_aux->customSetup(exec_type);
1295 }
1296 
1297 void
1299 {
1301 
1302  for (auto & nl : _displaced_solver_systems)
1303  nl->residualSetup();
1304  _displaced_aux->residualSetup();
1305 }
1306 
1307 void
1309 {
1311 
1312  for (auto & nl : _displaced_solver_systems)
1313  nl->jacobianSetup();
1314  _displaced_aux->jacobianSetup();
1315 }
1316 
1317 void
1318 DisplacedProblem::haveADObjects(const bool have_ad_objects)
1319 {
1320  _have_ad_objects = have_ad_objects;
1321  _mproblem.SubProblem::haveADObjects(have_ad_objects);
1322 }
1323 
1324 std::pair<bool, unsigned int>
1325 DisplacedProblem::determineSolverSystem(const std::string & var_name,
1326  const bool error_if_not_found) const
1327 {
1328  return _mproblem.determineSolverSystem(var_name, error_if_not_found);
1329 }
1330 
1331 Assembly &
1332 DisplacedProblem::assembly(const THREAD_ID tid, const unsigned int sys_num)
1333 {
1334  mooseAssert(tid < _assembly.size(), "Assembly objects not initialized");
1335  mooseAssert(sys_num < _assembly[tid].size(),
1336  "System number larger than the assembly container size");
1337  return *_assembly[tid][sys_num];
1338 }
1339 
1340 const Assembly &
1341 DisplacedProblem::assembly(const THREAD_ID tid, const unsigned int sys_num) const
1342 {
1343  mooseAssert(tid < _assembly.size(), "Assembly objects not initialized");
1344  mooseAssert(sys_num < _assembly[tid].size(),
1345  "System number larger than the assembly container size");
1346  return *_assembly[tid][sys_num];
1347 }
1348 
1349 std::size_t
1351 {
1352  return _mproblem.numNonlinearSystems();
1353 }
1354 
1355 std::size_t
1357 {
1358  return _mproblem.numLinearSystems();
1359 }
1360 
1361 std::size_t
1363 {
1364  return _mproblem.numSolverSystems();
1365 }
1366 
1367 const std::vector<VectorTag> &
1369 {
1371 }
1372 
1373 bool
1375 {
1377 }
1378 
1379 bool
1381 {
1383 }
1384 
1385 void
1387 {
1388  _mproblem.needFV();
1389 }
1390 
1391 bool
1393 {
1394  return _mproblem.haveFV();
1395 }
1396 
1397 bool
1399 {
1400  return _mproblem.hasNonlocalCoupling();
1401 }
1402 
1403 unsigned int
1404 DisplacedProblem::nlSysNum(const NonlinearSystemName & nl_sys_name) const
1405 {
1406  return _mproblem.nlSysNum(nl_sys_name);
1407 }
1408 
1409 unsigned int
1410 DisplacedProblem::linearSysNum(const LinearSystemName & sys_name) const
1411 {
1412  return _mproblem.linearSysNum(sys_name);
1413 }
1414 
1415 unsigned int
1416 DisplacedProblem::solverSysNum(const SolverSystemName & sys_name) const
1417 {
1418  return _mproblem.solverSysNum(sys_name);
1419 }
1420 
1423 {
1425 }
1426 
1427 bool
1429 {
1431 }
1432 
1435  : ThreadedNodeLoop<NodeRange, NodeRange::const_iterator>(fe_problem),
1436  _displaced_problem(displaced_problem),
1437  _ref_mesh(_displaced_problem.refMesh()),
1438  _nl_soln(_displaced_problem._nl_solution),
1439  _aux_soln(*_displaced_problem._aux_solution),
1440  _has_displacement(false)
1441 {
1442  this->init();
1443 }
1444 
1447  : ThreadedNodeLoop<NodeRange, NodeRange::const_iterator>(x, split),
1448  _displaced_problem(x._displaced_problem),
1449  _ref_mesh(x._ref_mesh),
1450  _nl_soln(x._nl_soln),
1451  _aux_soln(x._aux_soln),
1452  _sys_to_nonghost_and_ghost_soln(x._sys_to_nonghost_and_ghost_soln),
1453  _sys_to_var_num_and_direction(x._sys_to_var_num_and_direction),
1454  _has_displacement(x._has_displacement)
1455 {
1456 }
1457 
1458 void
1460 {
1461  std::vector<std::string> & displacement_variables = _displaced_problem._displacements;
1462  unsigned int num_displacements = displacement_variables.size();
1463  auto & es = _displaced_problem.es();
1464 
1465  _sys_to_var_num_and_direction.clear();
1466  _sys_to_nonghost_and_ghost_soln.clear();
1467 
1468  for (unsigned int i = 0; i < num_displacements; i++)
1469  {
1470  std::string displacement_name = displacement_variables[i];
1471 
1472  for (const auto sys_num : make_range(es.n_systems()))
1473  {
1474  auto & sys = es.get_system(sys_num);
1475  if (sys.has_variable(displacement_name))
1476  {
1477  auto & val = _sys_to_var_num_and_direction[sys.number()];
1478  val.first.push_back(sys.variable_number(displacement_name));
1479  val.second.push_back(i);
1480  break;
1481  }
1482  }
1483  }
1484 
1485  for (const auto & pr : _sys_to_var_num_and_direction)
1486  {
1487  auto & sys = es.get_system(pr.first);
1488  mooseAssert(sys.number() <= _nl_soln.size(),
1489  "The system number should always be less than or equal to the number of nonlinear "
1490  "systems. If it is equal, then this system is the auxiliary system");
1491  const NumericVector<Number> * const nonghost_soln =
1492  sys.number() < _nl_soln.size() ? _nl_soln[sys.number()] : &_aux_soln;
1493  _sys_to_nonghost_and_ghost_soln.emplace(
1494  sys.number(),
1495  std::make_pair(nonghost_soln,
1496  NumericVector<Number>::build(nonghost_soln->comm()).release()));
1497  }
1498 
1499  ConstNodeRange node_range(_ref_mesh.getMesh().nodes_begin(), _ref_mesh.getMesh().nodes_end());
1500 
1501  for (auto & [sys_num, var_num_and_direction] : _sys_to_var_num_and_direction)
1502  {
1503  auto & sys = es.get_system(sys_num);
1504  AllNodesSendListThread send_list(
1505  this->_fe_problem, _ref_mesh, var_num_and_direction.first, sys);
1506  Threads::parallel_reduce(node_range, send_list);
1507  send_list.unique();
1508  auto & [soln, ghost_soln] = libmesh_map_find(_sys_to_nonghost_and_ghost_soln, sys_num);
1509  ghost_soln->init(
1510  soln->size(), soln->local_size(), send_list.send_list(), true, libMesh::GHOSTED);
1511  soln->localize(*ghost_soln, send_list.send_list());
1512  }
1513 
1514  _has_displacement = false;
1515 }
1516 
1517 void
1519 {
1520  Node & displaced_node = *(*nd);
1521 
1522  Node & reference_node = _ref_mesh.nodeRef(displaced_node.id());
1523 
1524  for (auto & [sys_num, var_num_and_direction] : _sys_to_var_num_and_direction)
1525  {
1526  auto & var_numbers = var_num_and_direction.first;
1527  auto & directions = var_num_and_direction.second;
1528  for (const auto i : index_range(var_numbers))
1529  {
1530  const auto direction = directions[i];
1531  if (reference_node.n_dofs(sys_num, var_numbers[i]) > 0)
1532  {
1533  Real coord = reference_node(direction) +
1534  (*libmesh_map_find(_sys_to_nonghost_and_ghost_soln, sys_num).second)(
1535  reference_node.dof_number(sys_num, var_numbers[i], 0));
1536  if (displaced_node(direction) != coord)
1537  {
1538  displaced_node(direction) = coord;
1539  _has_displacement = true;
1540  }
1541  }
1542  }
1543  }
1544 }
virtual LineSearch * getLineSearch() override
VarFieldType
Definition: MooseTypes.h:770
GeometricSearchData _geometric_search_data
virtual TagID getVectorTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition: SubProblem.C:204
virtual void reinitNodesNeighbor(const std::vector< dof_id_type > &nodes, const THREAD_ID tid) override
virtual void addGhostedElem(dof_id_type elem_id) override
Will make sure that all dofs connected to elem_id are ghosted to this processor.
friend class UpdateDisplacedMeshThread
bool _have_ad_objects
AD flag indicating whether any AD objects have been added.
Definition: SubProblem.h:1121
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
virtual System & getSystem(const std::string &var_name) override
Returns the equation system containing the variable provided.
virtual void reinitNode(const Node *node, const THREAD_ID tid) override
Order
MooseVariableFieldBase & getVariableHelper(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type, Moose::VarFieldType expected_var_field_type, const std::vector< T > &nls, const SystemBase &aux) const
Helper function called by getVariable that handles the logic for checking whether Variables of the re...
virtual void addGhostedElem(dof_id_type elem_id) override
Will make sure that all dofs connected to elem_id are ghosted to this processor.
virtual void saveOldSolutions()
Allocate vectors and save old solutions into them.
unsigned int n_systems() const
virtual const char * what() const
Get out the error message.
unsigned int n_threads()
void undisplaceMesh()
Resets the displaced mesh to the reference mesh.
const std::set< SubdomainID > & interiorLowerDBlocks() const
Definition: MooseMesh.h:1549
std::shared_ptr< DisplacedProblem > displaced_problem
virtual void reinitLowerDElem(const Elem *lower_d_elem, const THREAD_ID tid, const std::vector< Point > *const pts=nullptr, const std::vector< Real > *const weights=nullptr)
Definition: SubProblem.C:958
virtual bool hasNonlocalCoupling() const override
Whether the simulation has active nonlocal coupling which should be accounted for in the Jacobian...
virtual void checkExceptionAndStopSolve(bool print_message=true)
Check to see if an exception has occurred on any processor and, if possible, force the solve to fail...
virtual void meshDisplaced()
Update data after a mesh displaced.
Keeps track of stuff related to assembling.
Definition: Assembly.h:109
void setCoordData(const MooseMesh &other_mesh)
Set the coordinate system data to that of other_mesh.
Definition: MooseMesh.C:4469
virtual void addAuxVariable(const std::string &var_type, const std::string &name, InputParameters &parameters)
unsigned int TagID
Definition: MooseTypes.h:238
virtual std::size_t numNonlinearSystems() const override
virtual MooseVariableFieldBase & getActualFieldVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested MooseVariableField which may be in any system...
virtual bool haveFV() const override
returns true if this problem includes/needs finite volume functionality.
virtual void residualSetup() override
void addPrivateParam(const std::string &name, const T &value)
These method add a parameter to the InputParameters object which can be retrieved like any other para...
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Definition: FEProblem.h:20
virtual void initAdaptivity()
void bumpAllQRuleOrder(Order order, SubdomainID block)
virtual bool safeAccessTaggedVectors() const
Is it safe to access the tagged vectors.
Definition: SubProblem.h:734
virtual void initialSetup() override
virtual bool computingPreSMOResidual(const unsigned int nl_sys_num) const override
Returns true if the problem is in the process of computing it&#39;s initial residual. ...
virtual std::pair< bool, unsigned int > determineSolverSystem(const std::string &var_name, bool error_if_not_found=false) const override
Determine what solver system the provided variable name lies in.
virtual void addJacobianNeighborLowerD(const THREAD_ID tid) override
virtual void needFV() override
marks this problem as including/needing finite volume functionality.
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL) override
Create a Tag.
const Elem * getLowerDElem(const Elem *, unsigned short int) const
Returns a const pointer to a lower dimensional element that corresponds to a side of a higher dimensi...
Definition: MooseMesh.C:1723
virtual bool checkNonlocalCouplingRequirement() const override
virtual void prepareShapes(unsigned int var, const THREAD_ID tid) override
virtual void allgather()
FEProblemBase & _mproblem
virtual numeric_index_type size() const=0
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:131
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition: SubProblem.C:93
virtual unsigned int currentLinearSysNum() const override
virtual void prepareNeighborShapes(unsigned int var, const THREAD_ID tid) override
virtual void createQRules(QuadratureType type, Order order, Order volume_order, Order face_order, SubdomainID block, bool allow_negative_qweights=true)
virtual void reinitNodes(const std::vector< dof_id_type > &nodes, const THREAD_ID tid) override
virtual void residualSetup()
Definition: SubProblem.C:1204
virtual EquationSystems & es() override
virtual void setException(const std::string &message)
Set an exception, which is stored at this point by toggling a member variable in this class...
virtual bool haveFV() const override
returns true if this problem includes/needs finite volume functionality.
virtual bool safeAccessTaggedMatrices() const override
Is it safe to access the tagged matrices.
virtual bool hasScalarVariable(const std::string &var_name) const override
Returns a Boolean indicating whether any system contains a variable with the name provided...
MeshBase & mesh
const NumericVector< Number > *const & currentSolution() const override
The solution vector that is currently being operated on.
virtual void prepareAssemblyNeighbor(const THREAD_ID tid)
virtual void gather_to_zero()
virtual void addGhostedBoundary(BoundaryID boundary_id) override
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
virtual const std::vector< VectorTag > & currentResidualVectorTags() const override
Return the residual vector tags we are currently computing.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
QuadratureType
UpdateDisplacedMeshThread(FEProblemBase &fe_problem, DisplacedProblem &displaced_problem)
bool hasDisplacement()
Whether the displaced mesh is modified by the latest call to operator()
virtual TagName vectorTagName(const TagID tag_id) const override
Retrieve the name associated with a TagID.
This class provides an interface for common operations on field variables of both FE and FV types wit...
virtual void addJacobianLowerD(const THREAD_ID tid) override
virtual TagID getMatrixTagID(const TagName &tag_name) const override
Get a TagID from a TagName.
virtual void jacobianSetup()
Definition: SubProblem.C:1212
virtual void timestepSetup() override
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
void computingScalingJacobian(bool computing_scaling_jacobian)
Setter for whether we&#39;re computing the scaling jacobian.
const T_sys & get_system(std::string_view name) const
virtual unsigned int numVectorTags(const Moose::VectorTagType type=Moose::VECTOR_TAG_ANY) const override
The total number of tags, which can be limited to the tag type.
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual std::size_t numSolverSystems() const override
registerMooseObject("MooseApp", DisplacedProblem)
virtual const Node & nodeRef(const dof_id_type i) const
Definition: MooseMesh.C:834
virtual void onTimestepBegin() override
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
std::vector< std::unique_ptr< DisplacedSystem > > _displaced_solver_systems
void syncSolutions()
Copy the solutions on the undisplaced systems to the displaced systems.
virtual void prepareBlockNonlocal(unsigned int ivar, unsigned int jvar, const std::vector< dof_id_type > &idof_indices, const std::vector< dof_id_type > &jdof_indices, const THREAD_ID tid)
virtual Elem * queryElemPtr(const dof_id_type i)
Definition: MooseMesh.C:3252
virtual std::set< dof_id_type > & ghostedElems() override
Return the list of elements that should have their DoFs ghosted to this processor.
virtual void reinitElemPhys(const Elem *elem, const std::vector< Point > &phys_points_in_elem, const THREAD_ID tid) override
virtual void reinitNeighbor(const Elem *elem, unsigned int side, const THREAD_ID tid) override
virtual bool is_serial_on_zero() const
virtual MooseVariable & getStandardVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested MooseVariable which may be in any system.
const libMesh::CouplingMatrix * couplingMatrix(const unsigned int nl_sys_num) const override
The coupling matrix defining what blocks exist in the preconditioning matrix.
virtual MooseVariableScalar & getScalarVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the scalar variable reference from whichever system contains it.
virtual bool computingPreSMOResidual(const unsigned int nl_sys_num) const override
Returns true if the problem is in the process of computing it&#39;s initial residual. ...
void update()
Update the system (doing libMesh magic)
Definition: SystemBase.C:1244
std::vector< std::vector< std::unique_ptr< Assembly > > > _assembly
DisplacedProblem(DisplacedProblem &&)=delete
virtual bool solverSystemConverged(const unsigned int solver_sys_num) override
virtual const std::string & name() const
Definition: SystemBase.C:1342
virtual void customSetup(const ExecFlagType &exec_type)
Definition: SubProblem.C:1196
unsigned int n_dofs(const unsigned int s, const unsigned int var=libMesh::invalid_uint) const
bool automaticScaling() const
Automatic scaling getter.
Definition: SubProblem.C:1163
bool hasJacobian() const
Returns _has_jacobian.
EquationSystems _eq
virtual bool is_serial() const
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
virtual unsigned int currentNlSysNum() const override
virtual const libMesh::CouplingMatrix & nonlocalCouplingMatrix(const unsigned i) const override
MultiPointMap & getPoints()
Returns a writeable reference to the _points container.
void clearQuadratureNodes()
Clear out any existing quadrature nodes.
Definition: MooseMesh.C:1700
dof_id_type id() const
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3575
std::vector< const NumericVector< Number > * > _nl_solution
The nonlinear system solutions.
virtual std::pair< bool, unsigned int > determineSolverSystem(const std::string &var_name, bool error_if_not_found=false) const override
MooseMesh & _ref_mesh
reference mesh
virtual bool computingScalingResidual() const override final
Getter for whether we&#39;re computing the scaling residual.
virtual TagID getMatrixTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition: SubProblem.C:343
void extraSendList(std::vector< dof_id_type > &send_list, void *context)
///< Type of coordinate system
Definition: SystemBase.C:40
unsigned int which_neighbor_am_i(const Elem *e) const
virtual void reinitElemFace(const Elem *elem, unsigned int side, const THREAD_ID tid) override
std::unique_ptr< DisplacedSystem > _displaced_aux
virtual void addJacobian(const THREAD_ID tid) override
virtual void setResidual(NumericVector< Number > &residual, const THREAD_ID tid) override
boundary_id_type BoundaryID
virtual void clearDiracInfo() override
Gets called before Dirac Kernels are asked to add the points they are supposed to be evaluated in...
bool constJacobian() const
Returns _const_jacobian (whether a MOOSE object has specified that the Jacobian is the same as the pr...
VarKindType
Framework-wide stuff.
Definition: MooseTypes.h:763
void computingScalingResidual(bool computing_scaling_residual)
Setter for whether we&#39;re computing the scaling residual.
virtual void restoreOldSolutions()
Restore old solutions from the backup vectors and deallocate them.
virtual const std::vector< VectorTag > & getVectorTags(const Moose::VectorTagType type=Moose::VECTOR_TAG_ANY) const override
Return all vector tags, where a tag is represented by a map from name to ID.
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Definition: SubProblem.C:312
virtual void setResidualNeighbor(NumericVector< Number > &residual, const THREAD_ID tid) override
virtual Moose::VectorTagType vectorTagType(const TagID tag_id) const
Definition: SubProblem.C:232
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:93
virtual bool converged(const unsigned int sys_num)
Eventually we want to convert this virtual over to taking a solver system number argument.
Definition: SubProblem.h:113
void clear_point_locator()
virtual unsigned int currentNlSysNum() const override
virtual unsigned int solverSysNum(const SolverSystemName &sys_name) const override
virtual void reinitNeighborPhys(const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > &physical_points, const THREAD_ID tid) override
const std::string & type() const
Get the type of this class.
Definition: MooseBase.h:93
virtual bool hasVariable(const std::string &var_name) const override
Whether or not this problem has the variable.
void reinit()
Completely redo all geometric search objects.
std::vector< VectorTag > getVectorTags(const std::set< TagID > &tag_ids) const
Definition: SubProblem.C:173
virtual void addVariable(const std::string &var_type, const std::string &name, InputParameters &parameters, unsigned int nl_system_number)
virtual Moose::VectorTagType vectorTagType(const TagID tag_id) const override
virtual void reinitOffDiagScalars(const THREAD_ID tid) override
virtual void addJacobianBlockTags(SparseMatrix< Number > &jacobian, unsigned int ivar, unsigned int jvar, const libMesh::DofMap &dof_map, std::vector< dof_id_type > &dof_indices, const std::set< TagID > &tags, const THREAD_ID tid)
LineSearch * getLineSearch() override
getter for the MOOSE line search
virtual std::set< dof_id_type > & ghostedElems()
Return the list of elements that should have their DoFs ghosted to this processor.
Definition: SubProblem.h:672
std::vector< std::string > _displacements
virtual bool vectorTagExists(const TagID tag_id) const
Check to see if a particular Tag exists.
Definition: SubProblem.h:201
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
virtual const VectorTag & getVectorTag(const TagID tag_id) const override
Get a VectorTag from a TagID.
void clearPoints()
Remove all of the current points and elements.
const NumericVector< Number > * _aux_solution
The auxiliary system solution.
virtual void addResidualLower(const THREAD_ID tid) override
AuxiliarySystem & getAuxiliarySystem()
bool haveADObjects() const
Method for reading wehther we have any ad objects.
Definition: SubProblem.h:771
virtual bool isTransient() const override
GeometricSearchType
Used to select groups of geometric search objects to update.
VectorTagType
Definition: MooseTypes.h:1027
virtual void onTimestepEnd() override
virtual std::size_t numNonlinearSystems() const override
virtual const libMesh::CouplingMatrix & nonlocalCouplingMatrix(const unsigned i) const override
virtual void reinitElem(const Elem *elem, const THREAD_ID tid) override
virtual void addCachedResidualDirectly(NumericVector< Number > &residual, const THREAD_ID tid)
virtual void timestepSetup()
Definition: SubProblem.C:1186
virtual unsigned int numMatrixTags() const
The total number of tags.
Definition: SubProblem.h:248
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
tbb::split split
virtual void customSetup(const ExecFlagType &exec_type) override
virtual TagName matrixTagName(TagID tag) override
Retrieve the name associated with a TagID.
const Elem * neighbor_ptr(unsigned int i) const
virtual void reinitNodeFace(const Node *node, BoundaryID bnd_id, const THREAD_ID tid) override
Provides a way for users to bail out of the current solve.
void syncAuxSolution(const NumericVector< Number > &aux_soln)
Copy the provided solution into the displaced auxiliary system.
void setCurrentSubdomainID(SubdomainID i)
set the current subdomain ID
Definition: Assembly.h:424
virtual void initialSetup()
Definition: SubProblem.C:1220
virtual void prepareAssembly(const THREAD_ID tid) override
virtual void prepare(const Elem *elem, const THREAD_ID tid) override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual bool contract()=0
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:78
subdomain_id_type subdomain_id() const
virtual VectorMooseVariable & getVectorVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested VectorMooseVariable which may be in any system...
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:18
unsigned int solverSysNum(const SolverSystemName &solver_sys_name) const override
vec_type::const_iterator const_iterator
virtual unsigned short dim() const=0
virtual bool matrixTagExists(const TagName &tag_name) const override
Check to see if a particular Tag exists.
virtual bool computingScalingJacobian() const override final
Getter for whether we&#39;re computing the scaling jacobian.
virtual TagID addMatrixTag(TagName tag_name) override
Create a Tag.
virtual void addResidualNeighbor(const THREAD_ID tid) override
void addJacobianBlockNonlocal(SparseMatrix< Number > &jacobian, unsigned int ivar, unsigned int jvar, const libMesh::DofMap &dof_map, const std::vector< dof_id_type > &idof_indices, const std::vector< dof_id_type > &jdof_indices, const std::set< TagID > &tags, const THREAD_ID tid)
virtual void addResidual(const THREAD_ID tid) override
virtual const std::vector< VectorTag > & currentResidualVectorTags() const override
Return the residual vector tags we are currently computing.
const std::vector< dof_id_type > & send_list() const
virtual void cacheJacobianNonlocal(const THREAD_ID tid)
void update(GeometricSearchType type=ALL)
Update all of the search objects.
Class for scalar variables (they are different).
IntRange< T > make_range(T beg, T end)
virtual unsigned int linearSysNum(const LinearSystemName &sys_name) const override
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
unsigned int linearSysNum(const LinearSystemName &linear_sys_name) const override
virtual unsigned int numVectorTags(const Moose::VectorTagType type=Moose::VECTOR_TAG_ANY) const
The total number of tags, which can be limited to the tag type.
Definition: SubProblem.C:196
virtual std::size_t numLinearSystems() const override
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid) override
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
virtual void prepareFaceShapes(unsigned int var, const THREAD_ID tid) override
virtual unsigned int numMatrixTags() const override
The total number of tags.
virtual void updateGeomSearch(GeometricSearchData::GeometricSearchType type=GeometricSearchData::ALL) override
virtual void reinitElemNeighborAndLowerD(const Elem *elem, unsigned int side, const THREAD_ID tid) override
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:147
std::set< const Elem * > & getElements()
Returns a writeable reference to the _elements container.
MooseMesh & refMesh()
virtual std::size_t numLinearSystems() const override
virtual bool reinitDirac(const Elem *elem, const THREAD_ID tid) override
Returns true if the Problem has Dirac kernels it needs to compute on elem.
virtual TagName vectorTagName(const TagID tag) const
Retrieve the name associated with a TagID.
Definition: SubProblem.C:222
virtual void setNeighborSubdomainID(const Elem *elem, unsigned int side, const THREAD_ID tid) override
static InputParameters validParams()
Definition: SubProblem.C:36
void automaticScaling(bool automatic_scaling) override
Automatic scaling setter.
virtual ArrayMooseVariable & getArrayVariable(const THREAD_ID tid, const std::string &var_name) override
Returns the variable reference for requested ArrayMooseVariable which may be in any system...
virtual void addJacobianNonlocal(const THREAD_ID tid)
virtual bool isTransient() const override
virtual void reinitScalars(const THREAD_ID tid, bool reinit_for_derivative_reordering=false) override
fills the VariableValue arrays for scalar variables from the solution vector
virtual bool safeAccessTaggedMatrices() const
Is it safe to access the tagged matrices.
Definition: SubProblem.h:731
virtual void updateMesh(bool mesh_changing=false)
Copy the solutions on the undisplaced systems to the displaced systems and reinitialize the geometry ...
virtual bool safeAccessTaggedVectors() const override
Is it safe to access the tagged vectors.
virtual void getDiracElements(std::set< const Elem *> &elems) override
Fills "elems" with the elements that should be looped over for Dirac Kernels.
virtual bool checkNonlocalCouplingRequirement() const override
void meshChanged(bool contract_mesh, bool clean_refinement_flags)
Storage for all of the information pretaining to a vector tag.
Definition: VectorTag.h:17
DiracKernelInfo _dirac_kernel_info
Definition: SubProblem.h:1056
virtual void jacobianSetup() override
void setCurrentNeighborSubdomainID(SubdomainID i)
set the current subdomain ID
Definition: Assembly.h:502
virtual void addGhostedBoundary(BoundaryID boundary_id) override
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
virtual void prepareNonlocal(const THREAD_ID tid)
virtual std::size_t numSolverSystems() const override
virtual unsigned int currentLinearSysNum() const override
virtual void needFV() override
marks this problem as including/needing finite volume functionality.
virtual void prepareFace(const Elem *elem, const THREAD_ID tid) override
virtual void onNode(NodeRange::const_iterator &nd) override
virtual TagID getVectorTagID(const TagName &tag_name) const override
Get a TagID from a TagName.
void addTimeIntegrator()
Get the time integrators from the problem.
virtual const VectorTag & getVectorTag(const TagID tag_id) const
Get a VectorTag from a TagID.
Definition: SubProblem.C:162
void updatePointLocator(const MooseMesh &mesh)
Called during FEProblemBase::meshChanged() to update the PointLocator object used by the DiracKernels...
auto index_range(const T &sizable)
virtual bool hasNonlocalCoupling() const override
Whether the simulation has active nonlocal coupling which should be accounted for in the Jacobian...
virtual const CouplingMatrix * couplingMatrix(const unsigned int nl_sys_num) const override
The coupling matrix defining what blocks exist in the preconditioning matrix.
virtual bool vectorTagExists(const TagID tag_id) const override
Check to see if a particular Tag exists.
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
virtual bool matrixTagExists(const TagName &tag_name) const
Check to see if a particular Tag exists.
Definition: SubProblem.C:329
virtual TagName matrixTagName(TagID tag)
Retrieve the name associated with a TagID.
Definition: SubProblem.C:358
void meshChanged()
Declares that the MooseMesh has changed, invalidates cached data and rebuilds caches.
Definition: MooseMesh.C:882
static InputParameters validParams()
unsigned int THREAD_ID
Definition: MooseTypes.h:237
virtual void ghostGhostedBoundaries() override
Causes the boundaries added using addGhostedBoundary to actually be ghosted.
uint8_t dof_id_type
void bumpVolumeQRuleOrder(Order order, SubdomainID block)
virtual void init() override
virtual void addJacobianNeighbor(const THREAD_ID tid) override
virtual void ghostGhostedBoundaries() override
Causes the boundaries added using addGhostedBoundary to actually be ghosted.
void setupFiniteVolumeMeshData() const
Sets up the additional data needed for finite volume computations.
Definition: MooseMesh.C:4219
Key structure for APIs manipulating global vectors/matrices.
Definition: Assembly.h:844