https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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"
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
30
33{
36 "A Problem object for providing access to the displaced finite element "
37 "mesh and associated variables.");
38 params.addPrivateParam<MooseMesh *>("mesh");
39 params.addPrivateParam<std::vector<std::string>>("displacements", {});
40 return params;
41}
42
44 : SubProblem(parameters),
45 _mproblem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base")
46 ? *getParam<FEProblemBase *>("_fe_problem_base")
47 : *getParam<FEProblem *>("_fe_problem")),
48 _mesh(*getParam<MooseMesh *>("mesh")),
49 _eq(_mesh),
50 _ref_mesh(_mproblem.mesh()),
51 _displacements(getParam<std::vector<std::string>>("displacements")),
52 _geometric_search_data(*this, _mesh)
53
54{
55 // Disable refinement/coarsening in EquationSystems::reinit because we already do this ourselves
56 _eq.disable_refine_in_reinit();
57
58 // TODO: Move newAssemblyArray further up to SubProblem so that we can use it here
59 unsigned int n_threads = this->numThreads();
60
61 _assembly.resize(n_threads);
62 for (const auto nl_sys_num : make_range(_mproblem.numNonlinearSystems()))
63 {
64 _displaced_solver_systems.emplace_back(std::make_unique<DisplacedSystem>(
65 *this,
68 "displaced_" + _mproblem.getNonlinearSystemBase(nl_sys_num).name() + "_" +
69 std::to_string(nl_sys_num),
71 auto & displaced_nl = _displaced_solver_systems.back();
72
73 for (unsigned int i = 0; i < n_threads; ++i)
74 _assembly[i].emplace_back(std::make_unique<Assembly>(*displaced_nl, i));
75 }
76
77 _nl_solution.resize(_displaced_solver_systems.size(), nullptr);
78
80 std::make_unique<DisplacedSystem>(*this,
83 "displaced_" + _mproblem.getAuxiliarySystem().name(),
85
86 // // Generally speaking, the mesh is prepared for use, and consequently remote elements are deleted
87 // // well before our Problem(s) are constructed. Historically, in MooseMesh we have a bunch of
88 // // needs_prepare type flags that make it so we never call prepare_for_use (and consequently
89 // // delete_remote_elements) again. So the below line, historically, has had no impact. HOWEVER:
90 // // I've added some code in SetupMeshCompleteAction for deleting remote elements post
91 // // EquationSystems::init. If I execute that code without default ghosting, then I get > 40 MOOSE
92 // // test failures, so we clearly have some simulations that are not yet covered properly by
93 // // relationship managers. Until that is resolved, I am going to retain default geometric ghosting
94 // if (!_default_ghosting)
95 // _mesh.getMesh().remove_ghosting_functor(_mesh.getMesh().default_ghosting());
96
98
100}
101
103
104bool
109
110std::set<dof_id_type> &
115
116void
118 Order order,
119 Order volume_order,
120 Order face_order,
121 SubdomainID block,
122 const bool allow_negative_qweights)
123{
124 for (unsigned int tid = 0; tid < this->numThreads(); ++tid)
125 for (const auto sys_num : index_range(_assembly[tid]))
126 _assembly[tid][sys_num]->createQRules(
127 type, order, volume_order, face_order, block, allow_negative_qweights);
128}
129
130void
132{
133 for (unsigned int tid = 0; tid < this->numThreads(); ++tid)
134 for (const auto nl_sys_num : index_range(_assembly[tid]))
135 _assembly[tid][nl_sys_num]->bumpVolumeQRuleOrder(order, block);
136}
137
138void
140{
141 for (unsigned int tid = 0; tid < this->numThreads(); ++tid)
142 for (const auto nl_sys_num : index_range(_assembly[tid]))
143 _assembly[tid][nl_sys_num]->bumpAllQRuleOrder(order, block);
144}
145
146void
148{
149 for (THREAD_ID tid = 0; tid < this->numThreads(); ++tid)
150 {
151 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
152 _assembly[tid][nl_sys_num]->init(_mproblem.couplingMatrix(nl_sys_num));
153
154 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
155 {
156 std::vector<std::pair<unsigned int, unsigned short>> disp_numbers_and_directions;
157 for (const auto direction : index_range(_displacements))
158 {
159 const auto & disp_string = _displacements[direction];
160 const auto & disp_variable = getVariable(tid, disp_string);
161 if (disp_variable.sys().number() == nl_sys_num)
162 disp_numbers_and_directions.push_back(
163 std::make_pair(disp_variable.number(), cast_int<unsigned short>(direction)));
164 }
165 _assembly[tid][nl_sys_num]->assignDisplacements(std::move(disp_numbers_and_directions));
166 }
167 }
168
169 for (auto & nl : _displaced_solver_systems)
170 {
171 nl->dofMap().attach_extra_send_list_function(&extraSendList, nl.get());
172 nl->preInit();
173 }
174
175 _displaced_aux->dofMap().attach_extra_send_list_function(&extraSendList, _displaced_aux.get());
176 _displaced_aux->preInit();
177
178 {
179 TIME_SECTION("eq::init", 2, "Initializing Displaced Equation System");
180 _eq.init();
181 }
182
183 for (auto & nl : _displaced_solver_systems)
184 nl->postInit();
185 _displaced_aux->postInit();
186
188
189 if (haveFV())
191}
192
193void
197
198void
200{
201 for (const auto nl_sys_num : make_range(_mproblem.numNonlinearSystems()))
202 _displaced_solver_systems[nl_sys_num]->copyTimeIntegrators(
204 _displaced_aux->copyTimeIntegrators(_mproblem.getAuxiliarySystem());
205}
206
207void
209{
210 for (auto & displaced_nl : _displaced_solver_systems)
211 displaced_nl->saveOldSolutions();
212 _displaced_aux->saveOldSolutions();
213}
214
215void
217{
218 for (auto & displaced_nl : _displaced_solver_systems)
219 displaced_nl->restoreOldSolutions();
220 _displaced_aux->restoreOldSolutions();
221}
222
223void
224DisplacedProblem::syncAuxSolution(const NumericVector<Number> & aux_soln)
225{
226 (*_displaced_aux->sys().solution) = aux_soln;
227 _displaced_aux->update();
228}
229
230void
232{
233 TIME_SECTION("syncSolutions", 5, "Syncing Displaced Solutions");
234
235 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
236 {
237 auto & displaced_nl = _displaced_solver_systems[nl_sys_num];
238 mooseAssert(nl_sys_num == displaced_nl->number(),
239 "We should have designed things such that the nl system numbers make their system "
240 "numbering in the EquationSystems object");
241 (*displaced_nl->sys().solution) =
242 *_mproblem.getNonlinearSystemBase(displaced_nl->number()).currentSolution();
243 displaced_nl->update();
244 }
246}
247
248void
250 const std::map<unsigned int, const NumericVector<Number> *> & nl_solns,
251 const NumericVector<Number> & aux_soln)
252{
253 TIME_SECTION("syncSolutions", 5, "Syncing Displaced Solutions");
254
255 for (const auto [nl_sys_num, nl_soln] : nl_solns)
256 {
257 (*_displaced_solver_systems[nl_sys_num]->sys().solution) = *nl_soln;
258 _displaced_solver_systems[nl_sys_num]->update();
259 }
260 syncAuxSolution(aux_soln);
261}
262
263void
265{
266 TIME_SECTION("updateMesh", 3, "Updating Displaced Mesh");
267
268 // If the mesh is changing, we are probably performing adaptivity. In that case, we do *not* want
269 // to use the undisplaced mesh solution because it may be out-of-sync, whereas our displaced mesh
270 // solution should be in the correct state after getting restricted/prolonged in
271 // EquationSystems::reinit (must have been called before this method)
272 if (!mesh_changing)
274
275 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
276 _nl_solution[nl_sys_num] = _displaced_solver_systems[nl_sys_num]->sys().solution.get();
277 _aux_solution = _displaced_aux->sys().solution.get();
278
279 // If the displaced mesh has been serialized to one processor (as
280 // may have occurred if it was used for Exodus output), then we need
281 // the reference mesh to be also. For that matter, did anyone
282 // somehow serialize the whole mesh? Hopefully not but let's avoid
283 // causing errors if so.
284 if (_mesh.getMesh().is_serial() && !this->refMesh().getMesh().is_serial())
285 this->refMesh().getMesh().allgather();
286
287 if (_mesh.getMesh().is_serial_on_zero() && !this->refMesh().getMesh().is_serial_on_zero())
288 this->refMesh().getMesh().gather_to_zero();
289
291
292 // We displace all nodes, not just semilocal nodes, because
293 // parallel-inconsistent mesh geometry makes libMesh cry.
294 NodeRange node_range(_mesh.getMesh().nodes_begin(),
295 _mesh.getMesh().nodes_end(),
296 /*grainsize=*/1);
297
298 Threads::parallel_reduce(node_range, udmt, this->numThreads());
299 // Stop on all processes before any geometric operation sees a non-finite displaced mesh
300 _mproblem.checkExceptionAndStopSolve(/*print_message=*/false);
301 // Displacement of the mesh has invalidated the point locator data (e.g. bounding boxes)
302 _mesh.getMesh().clear_point_locator();
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
338void
339DisplacedProblem::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, this->numThreads());
359 // Stop on all processes before any geometric operation sees a non-finite displaced mesh
360 _mproblem.checkExceptionAndStopSolve(/*print_message=*/false);
361
362 // Update the geometric searches that depend on the displaced mesh. This call can end up running
363 // NearestNodeThread::operator() which has a throw inside of it. We need to catch it and make sure
364 // it's propagated to all processes before updating the point locator because the latter requires
365 // communication
366 try
367 {
369 }
370 catch (MooseException & e)
371 {
373 }
374
375 if (udmt.hasDisplacement())
377
378 // The below call will throw an exception on all processes if any of our processes had an
379 // exception above. This exception will be caught higher up the call stack and the error message
380 // will be printed there
381 _mproblem.checkExceptionAndStopSolve(/*print_message=*/false);
382
383 // Since the Mesh changed, update the PointLocator object used by DiracKernels.
385}
386
387TagID
388DisplacedProblem::addVectorTag(const TagName & tag_name,
389 const Moose::VectorTagType type /* = Moose::VECTOR_TAG_RESIDUAL */)
390{
391 return _mproblem.addVectorTag(tag_name, type);
392}
393
394const VectorTag &
396{
397 return _mproblem.getVectorTag(tag_id);
398}
399
400TagID
401DisplacedProblem::getVectorTagID(const TagName & tag_name) const
402{
403 return _mproblem.getVectorTagID(tag_name);
404}
405
406TagName
408{
409 return _mproblem.vectorTagName(tag_id);
410}
411
412bool
414{
415 return _mproblem.vectorTagExists(tag_id);
416}
417
418bool
419DisplacedProblem::vectorTagExists(const TagName & tag_name) const
420{
421 return _mproblem.vectorTagExists(tag_name);
422}
423
424unsigned int
425DisplacedProblem::numVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
426{
428}
429
430const std::vector<VectorTag> &
431DisplacedProblem::getVectorTags(const Moose::VectorTagType type /* = Moose::VECTOR_TAG_ANY */) const
432{
434}
435
438{
439 return _mproblem.vectorTagType(tag_id);
440}
441
442TagID
444{
445 return _mproblem.addMatrixTag(tag_name);
446}
447
448TagID
449DisplacedProblem::getMatrixTagID(const TagName & tag_name) const
450{
451 return _mproblem.getMatrixTagID(tag_name);
452}
453
454TagName
459
460bool
461DisplacedProblem::matrixTagExists(const TagName & tag_name) const
462{
463 return _mproblem.matrixTagExists(tag_name);
464}
465
466bool
468{
469 return _mproblem.matrixTagExists(tag_id);
470}
471
472unsigned int
477
478bool
479DisplacedProblem::hasVariable(const std::string & var_name) const
480{
481 for (auto & nl : _displaced_solver_systems)
482 if (nl->hasVariable(var_name))
483 return true;
484 if (_displaced_aux->hasVariable(var_name))
485 return true;
486
487 return false;
488}
489
492 const std::string & var_name,
493 Moose::VarKindType expected_var_type,
494 Moose::VarFieldType expected_var_field_type) const
495{
496 return getVariableHelper(tid,
497 var_name,
498 expected_var_type,
499 expected_var_field_type,
502}
503
505DisplacedProblem::getStandardVariable(const THREAD_ID tid, const std::string & var_name)
506{
507 for (auto & nl : _displaced_solver_systems)
508 if (nl->hasVariable(var_name))
509 return nl->getFieldVariable<Real>(tid, var_name);
510 if (_displaced_aux->hasVariable(var_name))
511 return _displaced_aux->getFieldVariable<Real>(tid, var_name);
512
513 mooseError("No variable with name '" + var_name + "'");
514}
515
517DisplacedProblem::getActualFieldVariable(const THREAD_ID tid, const std::string & var_name)
518{
519 for (auto & nl : _displaced_solver_systems)
520 if (nl->hasVariable(var_name))
521 return nl->getActualFieldVariable<Real>(tid, var_name);
522 if (_displaced_aux->hasVariable(var_name))
523 return _displaced_aux->getActualFieldVariable<Real>(tid, var_name);
524
525 mooseError("No variable with name '" + var_name + "'");
526}
527
529DisplacedProblem::getVectorVariable(const THREAD_ID tid, const std::string & var_name)
530{
531 for (auto & nl : _displaced_solver_systems)
532 if (nl->hasVariable(var_name))
533 return nl->getFieldVariable<RealVectorValue>(tid, var_name);
534 if (_displaced_aux->hasVariable(var_name))
535 return _displaced_aux->getFieldVariable<RealVectorValue>(tid, var_name);
536
537 mooseError("No variable with name '" + var_name + "'");
538}
539
541DisplacedProblem::getArrayVariable(const THREAD_ID tid, const std::string & var_name)
542{
543 for (auto & nl : _displaced_solver_systems)
544 if (nl->hasVariable(var_name))
545 return nl->getFieldVariable<RealEigenVector>(tid, var_name);
546 if (_displaced_aux->hasVariable(var_name))
547 return _displaced_aux->getFieldVariable<RealEigenVector>(tid, var_name);
548
549 mooseError("No variable with name '" + var_name + "'");
550}
551
552bool
553DisplacedProblem::hasScalarVariable(const std::string & var_name) const
554{
555 for (auto & nl : _displaced_solver_systems)
556 if (nl->hasScalarVariable(var_name))
557 return true;
558 if (_displaced_aux->hasScalarVariable(var_name))
559 return true;
560
561 return false;
562}
563
565DisplacedProblem::getScalarVariable(const THREAD_ID tid, const std::string & var_name)
566{
567 for (auto & nl : _displaced_solver_systems)
568 if (nl->hasScalarVariable(var_name))
569 return nl->getScalarVariable(tid, var_name);
570 if (_displaced_aux->hasScalarVariable(var_name))
571 return _displaced_aux->getScalarVariable(tid, var_name);
572
573 mooseError("No variable with name '" + var_name + "'");
574}
575
576System &
577DisplacedProblem::getSystem(const std::string & var_name)
578{
579 for (const auto sys_num : make_range(_eq.n_systems()))
580 {
581 auto & sys = _eq.get_system(sys_num);
582 if (sys.has_variable(var_name))
583 return sys;
584 }
585
586 mooseError("Unable to find a system containing the variable " + var_name);
587}
588
589void
590DisplacedProblem::addVariable(const std::string & var_type,
591 const std::string & name,
592 InputParameters & parameters,
593 const unsigned int nl_system_number)
594{
595 _displaced_solver_systems[nl_system_number]->addVariable(var_type, name, parameters);
596}
597
598void
599DisplacedProblem::addAuxVariable(const std::string & var_type,
600 const std::string & name,
601 InputParameters & parameters)
602{
603 _displaced_aux->addVariable(var_type, name, parameters);
604}
605
606unsigned int
611
612unsigned int
617
618void
619DisplacedProblem::prepare(const Elem * elem, const THREAD_ID tid)
620{
621 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
622 {
623 _assembly[tid][nl_sys_num]->reinit(elem);
624 _displaced_solver_systems[nl_sys_num]->prepare(tid);
625 // This method is called outside of residual/Jacobian callbacks during initial condition
626 // evaluation
628 _assembly[tid][nl_sys_num]->prepareJacobianBlock();
629 _assembly[tid][nl_sys_num]->prepareResidual();
630 }
631
632 _displaced_aux->prepare(tid);
633}
634
635void
637{
638 _assembly[tid][currentNlSysNum()]->prepareNonlocal();
639}
640
641void
642DisplacedProblem::prepareFace(const Elem * /*elem*/, const THREAD_ID tid)
643{
644 for (auto & nl : _displaced_solver_systems)
645 nl->prepareFace(tid, true);
646 _displaced_aux->prepareFace(tid, false);
647}
648
649void
651 unsigned int ivar,
652 unsigned int jvar,
653 const std::vector<dof_id_type> & dof_indices,
654 const THREAD_ID tid)
655{
656 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
657 {
658 _assembly[tid][nl_sys_num]->reinit(elem);
659 _displaced_solver_systems[nl_sys_num]->prepare(tid);
660 }
661 _displaced_aux->prepare(tid);
662 _assembly[tid][currentNlSysNum()]->prepareBlock(ivar, jvar, dof_indices);
663}
664
665void
667{
668 SubdomainID did = elem->subdomain_id();
669 for (auto & assembly : _assembly[tid])
671}
672
673void
674DisplacedProblem::setNeighborSubdomainID(const Elem * elem, unsigned int side, const THREAD_ID tid)
675{
676 SubdomainID did = elem->neighbor_ptr(side)->subdomain_id();
677 for (auto & assembly : _assembly[tid])
679}
680
681void
683 unsigned int jvar,
684 const std::vector<dof_id_type> & idof_indices,
685 const std::vector<dof_id_type> & jdof_indices,
686 const THREAD_ID tid)
687{
688 _assembly[tid][currentNlSysNum()]->prepareBlockNonlocal(ivar, jvar, idof_indices, jdof_indices);
689}
690
691void
693{
694 _assembly[tid][currentNlSysNum()]->prepare();
695}
696
697void
699{
700 _assembly[tid][currentNlSysNum()]->prepareNeighbor();
701}
702
703bool
704DisplacedProblem::reinitDirac(const Elem * elem, const THREAD_ID tid)
705{
706 std::vector<Point> & points = _dirac_kernel_info.getPoints()[elem].first;
707
708 unsigned int n_points = points.size();
709
710 if (n_points)
711 {
712 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
713 {
714 _assembly[tid][nl_sys_num]->reinitAtPhysical(elem, points);
715 _displaced_solver_systems[nl_sys_num]->prepare(tid);
716 }
717 _displaced_aux->prepare(tid);
718
719 reinitElem(elem, tid);
720 }
721
722 _assembly[tid][currentNlSysNum()]->prepare();
723
724 return n_points > 0;
725}
726
727void
728DisplacedProblem::reinitElem(const Elem * elem, const THREAD_ID tid)
729{
730 for (auto & nl : _displaced_solver_systems)
731 nl->reinitElem(elem, tid);
732 _displaced_aux->reinitElem(elem, tid);
733}
734
735void
737 const std::vector<Point> & phys_points_in_elem,
738 const THREAD_ID tid)
739{
740 mooseAssert(_mesh.queryElemPtr(elem->id()) == elem,
741 "Are you calling this method with a undisplaced mesh element?");
742
743 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
744 {
745 _assembly[tid][nl_sys_num]->reinitAtPhysical(elem, phys_points_in_elem);
746 _displaced_solver_systems[nl_sys_num]->prepare(tid);
747 _assembly[tid][nl_sys_num]->prepare();
748 }
749 _displaced_aux->prepare(tid);
750
751 reinitElem(elem, tid);
752}
753
754void
755DisplacedProblem::reinitElemFace(const Elem * elem, unsigned int side, const THREAD_ID tid)
756{
757 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
758 {
759 _assembly[tid][nl_sys_num]->reinit(elem, side);
760 _displaced_solver_systems[nl_sys_num]->reinitElemFace(elem, side, tid);
761 }
762 _displaced_aux->reinitElemFace(elem, side, tid);
763}
764
765void
766DisplacedProblem::reinitNode(const Node * node, const THREAD_ID tid)
767{
768 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
769 {
770 _assembly[tid][nl_sys_num]->reinit(node);
771 _displaced_solver_systems[nl_sys_num]->reinitNode(node, tid);
772 }
773 _displaced_aux->reinitNode(node, tid);
774}
775
776void
777DisplacedProblem::reinitNodeFace(const Node * node, BoundaryID bnd_id, const THREAD_ID tid)
778{
779 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
780 {
781 _assembly[tid][nl_sys_num]->reinit(node);
782 _displaced_solver_systems[nl_sys_num]->reinitNodeFace(node, bnd_id, tid);
783 }
784 _displaced_aux->reinitNodeFace(node, bnd_id, tid);
785}
786
787void
788DisplacedProblem::reinitNeighbor(const Elem * elem, unsigned int side, const THREAD_ID tid)
789{
790 reinitNeighbor(elem, side, tid, nullptr);
791}
792
793void
795 unsigned int side,
796 const THREAD_ID tid,
797 const std::vector<Point> * neighbor_reference_points)
798{
799 setNeighborSubdomainID(elem, side, tid);
800
801 const Elem * neighbor = elem->neighbor_ptr(side);
802 unsigned int neighbor_side = neighbor->which_neighbor_am_i(elem);
803
804 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
805 {
806 _assembly[tid][nl_sys_num]->reinitElemAndNeighbor(
807 elem, side, neighbor, neighbor_side, neighbor_reference_points);
808 _displaced_solver_systems[nl_sys_num]->prepareNeighbor(tid);
809 // Called during stateful material property evaluation outside of solve
810 _assembly[tid][nl_sys_num]->prepareNeighbor();
811 }
812 _displaced_aux->prepareNeighbor(tid);
813
814 for (auto & nl : _displaced_solver_systems)
815 {
816 nl->reinitElemFace(elem, side, tid);
817 nl->reinitNeighborFace(neighbor, neighbor_side, tid);
818 }
819 _displaced_aux->reinitElemFace(elem, side, tid);
820 _displaced_aux->reinitNeighborFace(neighbor, neighbor_side, tid);
821}
822
823void
825 unsigned int neighbor_side,
826 const std::vector<Point> & physical_points,
827 const THREAD_ID tid)
828{
829 mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
830 "Are you calling this method with a undisplaced mesh element?");
831
832 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
833 {
834 // Reinit shape functions
835 _assembly[tid][nl_sys_num]->reinitNeighborAtPhysical(neighbor, neighbor_side, physical_points);
836
837 // Set the neighbor dof indices
838 _displaced_solver_systems[nl_sys_num]->prepareNeighbor(tid);
839 }
840 _displaced_aux->prepareNeighbor(tid);
841
843
844 // Compute values at the points
845 for (auto & nl : _displaced_solver_systems)
846 nl->reinitNeighborFace(neighbor, neighbor_side, tid);
847 _displaced_aux->reinitNeighborFace(neighbor, neighbor_side, tid);
848}
849
850void
852 const std::vector<Point> & physical_points,
853 const THREAD_ID tid)
854{
855 mooseAssert(_mesh.queryElemPtr(neighbor->id()) == neighbor,
856 "Are you calling this method with a undisplaced mesh element?");
857
858 for (const auto nl_sys_num : index_range(_displaced_solver_systems))
859 {
860 // Reinit shape functions
861 _assembly[tid][nl_sys_num]->reinitNeighborAtPhysical(neighbor, physical_points);
862
863 // Set the neighbor dof indices
864 _displaced_solver_systems[nl_sys_num]->prepareNeighbor(tid);
865 }
866 _displaced_aux->prepareNeighbor(tid);
867
869
870 // Compute values at the points
871 for (auto & nl : _displaced_solver_systems)
872 nl->reinitNeighbor(neighbor, tid);
873 _displaced_aux->reinitNeighbor(neighbor, tid);
874}
875
876void
878 unsigned int side,
879 const THREAD_ID tid)
880{
881 reinitNeighbor(elem, side, tid);
882
883 const Elem * lower_d_elem = _mesh.getLowerDElem(elem, side);
884 if (lower_d_elem && _mesh.interiorLowerDBlocks().count(lower_d_elem->subdomain_id()) > 0)
885 reinitLowerDElem(lower_d_elem, tid);
886 else
887 {
888 // with mesh refinement, lower-dimensional element might be defined on neighbor side
889 auto & neighbor = _assembly[tid][currentNlSysNum()]->neighbor();
890 auto & neighbor_side = _assembly[tid][currentNlSysNum()]->neighborSide();
891 const Elem * lower_d_elem_neighbor = _mesh.getLowerDElem(neighbor, neighbor_side);
892 if (lower_d_elem_neighbor &&
893 _mesh.interiorLowerDBlocks().count(lower_d_elem_neighbor->subdomain_id()) > 0)
894 {
895 auto qps = _assembly[tid][currentNlSysNum()]->qPointsFaceNeighbor().stdVector();
896 std::vector<Point> reference_points;
897 FEMap::inverse_map(
898 lower_d_elem_neighbor->dim(), lower_d_elem_neighbor, qps, reference_points);
899 reinitLowerDElem(lower_d_elem_neighbor, tid, &qps);
900 }
901 }
902}
903
904void
906 bool reinit_for_derivative_reordering /*=false*/)
907{
908 for (auto & nl : _displaced_solver_systems)
909 nl->reinitScalars(tid, reinit_for_derivative_reordering);
910 _displaced_aux->reinitScalars(tid, reinit_for_derivative_reordering);
911}
912
913void
915{
916 _assembly[tid][currentNlSysNum()]->prepareOffDiagScalar();
917}
918
919void
920DisplacedProblem::getDiracElements(std::set<const Elem *> & elems)
921{
923}
924
925void
930
931void
937
938void
944
945void
951
952void
953DisplacedProblem::addCachedResidualDirectly(NumericVector<Number> & residual, const THREAD_ID tid)
954{
956 _displaced_solver_systems[currentNlSysNum()]->timeVectorTag()))
957 _assembly[tid][currentNlSysNum()]->addCachedResidualDirectly(
958 residual,
961
963 _displaced_solver_systems[currentNlSysNum()]->nonTimeVectorTag()))
964 _assembly[tid][currentNlSysNum()]->addCachedResidualDirectly(
965 residual,
968
969 std::vector<VectorTag> extra_residual_vector_tags;
970 extra_residual_vector_tags.reserve(currentResidualVectorTags().size());
971 const auto time_tag = _displaced_solver_systems[currentNlSysNum()]->timeVectorTag();
972 const auto non_time_tag = _displaced_solver_systems[currentNlSysNum()]->nonTimeVectorTag();
973 for (const auto & vector_tag : currentResidualVectorTags())
974 if (vector_tag._id != time_tag && vector_tag._id != non_time_tag)
975 extra_residual_vector_tags.push_back(vector_tag);
976
977 // Flush extra vector tag caches (e.g. from extra_vector_tags on NodalConstraints)
978 // to their respective system vectors after the standard TIME/NONTIME caches above.
979 // Without this, NodalConstraint contributions to extra vector tags are silently
980 // discarded by the blanket clearCachedResiduals.
981 _assembly[tid][currentNlSysNum()]->addCachedResiduals(Assembly::GlobalDataKey{},
982 extra_residual_vector_tags);
983
984 // We do this because by adding the cached residual directly, we cannot ensure that all of the
985 // cached residuals are emptied after only the two add calls above
986 _assembly[tid][currentNlSysNum()]->clearCachedResiduals(Assembly::GlobalDataKey{});
987}
988
989void
990DisplacedProblem::setResidual(NumericVector<Number> & residual, const THREAD_ID tid)
991{
992 _assembly[tid][currentNlSysNum()]->setResidual(
993 residual,
996}
997
998void
999DisplacedProblem::setResidualNeighbor(NumericVector<Number> & residual, const THREAD_ID tid)
1000{
1001 _assembly[tid][currentNlSysNum()]->setResidualNeighbor(
1002 residual,
1004 getVectorTag(_displaced_solver_systems[currentNlSysNum()]->residualVectorTag()));
1005}
1006
1007void
1012
1013void
1015{
1016 _assembly[tid][currentNlSysNum()]->addJacobianNonlocal(Assembly::GlobalDataKey{});
1017}
1018
1019void
1021{
1022 _assembly[tid][currentNlSysNum()]->addJacobianNeighbor(Assembly::GlobalDataKey{});
1023}
1024
1025void
1027{
1028 _assembly[tid][currentNlSysNum()]->addJacobianNeighborLowerD(Assembly::GlobalDataKey{});
1029}
1030
1031void
1033{
1034 _assembly[tid][currentNlSysNum()]->addJacobianLowerD(Assembly::GlobalDataKey{});
1035}
1036
1037void
1039{
1040 _assembly[tid][currentNlSysNum()]->cacheJacobianNonlocal(Assembly::GlobalDataKey{});
1041}
1042
1043void
1044DisplacedProblem::addJacobianBlockTags(SparseMatrix<Number> & jacobian,
1045 unsigned int ivar,
1046 unsigned int jvar,
1047 const DofMap & dof_map,
1048 std::vector<dof_id_type> & dof_indices,
1049 const std::set<TagID> & tags,
1050 const THREAD_ID tid)
1051{
1052 _assembly[tid][currentNlSysNum()]->addJacobianBlockTags(
1053 jacobian, ivar, jvar, dof_map, dof_indices, Assembly::GlobalDataKey{}, tags);
1054}
1055
1056void
1057DisplacedProblem::addJacobianBlockNonlocal(SparseMatrix<Number> & jacobian,
1058 unsigned int ivar,
1059 unsigned int jvar,
1060 const DofMap & dof_map,
1061 const std::vector<dof_id_type> & idof_indices,
1062 const std::vector<dof_id_type> & jdof_indices,
1063 const std::set<TagID> & tags,
1064 const THREAD_ID tid)
1065{
1066 _assembly[tid][currentNlSysNum()]->addJacobianBlockNonlocalTags(
1067 jacobian, ivar, jvar, dof_map, idof_indices, jdof_indices, Assembly::GlobalDataKey{}, tags);
1068}
1069
1070void
1071DisplacedProblem::addJacobianNeighbor(SparseMatrix<Number> & jacobian,
1072 unsigned int ivar,
1073 unsigned int jvar,
1074 const DofMap & dof_map,
1075 std::vector<dof_id_type> & dof_indices,
1076 std::vector<dof_id_type> & neighbor_dof_indices,
1077 const std::set<TagID> & tags,
1078 const THREAD_ID tid)
1079{
1080 _assembly[tid][currentNlSysNum()]->addJacobianNeighborTags(jacobian,
1081 ivar,
1082 jvar,
1083 dof_map,
1084 dof_indices,
1085 neighbor_dof_indices,
1087 tags);
1088}
1089
1090void
1091DisplacedProblem::prepareShapes(unsigned int var, const THREAD_ID tid)
1092{
1093 _assembly[tid][currentNlSysNum()]->copyShapes(var);
1094}
1095
1096void
1098{
1099 _assembly[tid][currentNlSysNum()]->copyFaceShapes(var);
1100}
1101
1102void
1104{
1105 _assembly[tid][currentNlSysNum()]->copyNeighborShapes(var);
1106}
1107
1108void
1110{
1111 TIME_SECTION("updateGeometricSearch", 3, "Updating Displaced GeometricSearch");
1112
1114}
1115
1116void
1117DisplacedProblem::meshChanged(const bool contract_mesh, const bool clean_refinement_flags)
1118{
1119 // The mesh changed. The displaced equations system object only holds Systems, so calling
1120 // EquationSystems::reinit only prolongs/restricts the solution vectors, which is something that
1121 // needs to happen for every step of mesh adaptivity.
1122 _eq.reinit();
1123 if (contract_mesh)
1124 // Once vectors are restricted, we can delete children of coarsened elements
1125 _mesh.getMesh().contract();
1126 if (clean_refinement_flags)
1127 {
1128 // Finally clean refinement flags so that if someone tries to project vectors again without
1129 // an intervening mesh refinement to clean flags they won't run into trouble
1131 refinement.clean_refinement_flags();
1132 }
1133
1134 // Since the mesh has changed, we need to make sure that we update any of our
1135 // MOOSE-system specific data.
1136 for (auto & nl : _displaced_solver_systems)
1137 nl->reinit();
1138 _displaced_aux->reinit();
1139
1140 // We've performed some mesh adaptivity. We need to
1141 // clear any quadrature nodes such that when we build the boundary node lists in
1142 // MooseMesh::meshChanged we don't have any extraneous extra boundary nodes lying around
1144
1146
1147 // Before performing mesh adaptivity we un-displaced the mesh. We need to re-displace the mesh and
1148 // then reinitialize GeometricSearchData such that we have all the correct geometric information
1149 // for the changed mesh
1150 updateMesh(/*mesh_changing=*/true);
1151}
1152
1153void
1155{
1156 _mproblem.addGhostedElem(elem_id);
1157}
1158
1159void
1164
1165void
1170
1171MooseMesh &
1173{
1174 return _ref_mesh;
1175}
1176
1177bool
1179{
1180 return _mproblem.converged(sys_num);
1181}
1182
1183bool
1184DisplacedProblem::computingPreSMOResidual(const unsigned int nl_sys_num) const
1185{
1186 return _mproblem.computingPreSMOResidual(nl_sys_num);
1187}
1188
1189void
1193
1194void
1198
1199void
1201{
1202 // If undisplaceMesh() is called during initial adaptivity, it is
1203 // not valid to call _mesh.getActiveSemiLocalNodeRange() since it is
1204 // not set up yet. So we are creating the Range by hand.
1205 //
1206 // We must undisplace *all* our nodes to the _ref_mesh
1207 // configuration, not just the local ones, since the partitioners
1208 // require this. We are using the GRAIN_SIZE=1 from MooseMesh.C,
1209 // not sure how this value was decided upon.
1210 //
1211 // (DRG: The grainsize parameter is ultimately passed to TBB to help
1212 // it choose how to split up the range. A grainsize of 1 says "split
1213 // it as much as you want". Years ago I experimentally found that it
1214 // didn't matter much and that using 1 was fine.)
1215 //
1216 // Note: we don't have to invalidate/update as much stuff as
1217 // DisplacedProblem::updateMesh() does, since this will be handled
1218 // by a later call to updateMesh().
1219 NodeRange node_range(_mesh.getMesh().nodes_begin(),
1220 _mesh.getMesh().nodes_end(),
1221 /*grainsize=*/1);
1222
1224
1225 // Undisplace the mesh using threads.
1226 Threads::parallel_reduce(node_range, rdmt, this->numThreads());
1227}
1228
1229LineSearch *
1234
1235const CouplingMatrix *
1236DisplacedProblem::couplingMatrix(const unsigned int nl_sys_num) const
1237{
1238 return _mproblem.couplingMatrix(nl_sys_num);
1239}
1240
1241bool
1246
1247bool
1252
1253void
1255{
1257
1258 for (auto & nl : _displaced_solver_systems)
1259 nl->initialSetup();
1260 _displaced_aux->initialSetup();
1261}
1262
1263void
1265{
1267
1268 for (auto & nl : _displaced_solver_systems)
1269 nl->timestepSetup();
1270 _displaced_aux->timestepSetup();
1271}
1272
1273void
1275{
1276 SubProblem::customSetup(exec_type);
1277
1278 for (auto & nl : _displaced_solver_systems)
1279 nl->customSetup(exec_type);
1280 _displaced_aux->customSetup(exec_type);
1281}
1282
1283void
1285{
1287
1288 for (auto & nl : _displaced_solver_systems)
1289 nl->residualSetup();
1290 _displaced_aux->residualSetup();
1291}
1292
1293void
1295{
1297
1298 for (auto & nl : _displaced_solver_systems)
1299 nl->jacobianSetup();
1300 _displaced_aux->jacobianSetup();
1301}
1302
1303void
1304DisplacedProblem::haveADObjects(const bool have_ad_objects)
1305{
1306 _have_ad_objects = have_ad_objects;
1307 _mproblem.SubProblem::haveADObjects(have_ad_objects);
1308}
1309
1310std::pair<bool, unsigned int>
1311DisplacedProblem::determineSolverSystem(const std::string & var_name,
1312 const bool error_if_not_found) const
1313{
1314 return _mproblem.determineSolverSystem(var_name, error_if_not_found);
1315}
1316
1317Assembly &
1318DisplacedProblem::assembly(const THREAD_ID tid, const unsigned int sys_num)
1319{
1320 mooseAssert(tid < _assembly.size(), "Assembly objects not initialized");
1321 mooseAssert(sys_num < _assembly[tid].size(),
1322 "System number larger than the assembly container size");
1323 return *_assembly[tid][sys_num];
1324}
1325
1326const Assembly &
1327DisplacedProblem::assembly(const THREAD_ID tid, const unsigned int sys_num) const
1328{
1329 mooseAssert(tid < _assembly.size(), "Assembly objects not initialized");
1330 mooseAssert(sys_num < _assembly[tid].size(),
1331 "System number larger than the assembly container size");
1332 return *_assembly[tid][sys_num];
1333}
1334
1335std::size_t
1340
1341std::size_t
1346
1347std::size_t
1352
1353const std::vector<VectorTag> &
1358
1359bool
1364
1365bool
1370
1371void
1376
1377bool
1379{
1380 return _mproblem.haveFV();
1381}
1382
1383bool
1388
1389unsigned int
1390DisplacedProblem::nlSysNum(const NonlinearSystemName & nl_sys_name) const
1391{
1392 return _mproblem.nlSysNum(nl_sys_name);
1393}
1394
1395unsigned int
1396DisplacedProblem::linearSysNum(const LinearSystemName & sys_name) const
1397{
1398 return _mproblem.linearSysNum(sys_name);
1399}
1400
1401unsigned int
1402DisplacedProblem::solverSysNum(const SolverSystemName & sys_name) const
1403{
1404 return _mproblem.solverSysNum(sys_name);
1405}
1406
1409{
1411}
1412
1413bool
1418
1421 : ThreadedNodeLoop<NodeRange, NodeRange::const_iterator>(fe_problem),
1422 _displaced_problem(displaced_problem),
1423 _ref_mesh(_displaced_problem.refMesh()),
1424 _nl_soln(_displaced_problem._nl_solution),
1425 _aux_soln(*_displaced_problem._aux_solution),
1426 _has_displacement(false)
1427{
1428 this->init();
1429}
1430
1433 : ThreadedNodeLoop<NodeRange, NodeRange::const_iterator>(x, split),
1434 _displaced_problem(x._displaced_problem),
1436 _nl_soln(x._nl_soln),
1437 _aux_soln(x._aux_soln),
1438 _sys_to_nonghost_and_ghost_soln(x._sys_to_nonghost_and_ghost_soln),
1439 _sys_to_var_num_and_direction(x._sys_to_var_num_and_direction),
1440 _has_displacement(x._has_displacement)
1441{
1442}
1443
1444void
1446{
1447 std::vector<std::string> & displacement_variables = _displaced_problem._displacements;
1448 unsigned int num_displacements = displacement_variables.size();
1449 auto & es = _displaced_problem.es();
1450
1451 _sys_to_var_num_and_direction.clear();
1452 _sys_to_nonghost_and_ghost_soln.clear();
1453
1454 for (unsigned int i = 0; i < num_displacements; i++)
1455 {
1456 std::string displacement_name = displacement_variables[i];
1457
1458 for (const auto sys_num : make_range(es.n_systems()))
1459 {
1460 auto & sys = es.get_system(sys_num);
1461 if (sys.has_variable(displacement_name))
1462 {
1463 auto & val = _sys_to_var_num_and_direction[sys.number()];
1464 val.first.push_back(sys.variable_number(displacement_name));
1465 val.second.push_back(i);
1466 break;
1467 }
1468 }
1469 }
1470
1471 for (const auto & pr : _sys_to_var_num_and_direction)
1472 {
1473 auto & sys = es.get_system(pr.first);
1474 mooseAssert(sys.number() <= _nl_soln.size(),
1475 "The system number should always be less than or equal to the number of nonlinear "
1476 "systems. If it is equal, then this system is the auxiliary system");
1477 const NumericVector<Number> * const nonghost_soln =
1478 sys.number() < _nl_soln.size() ? _nl_soln[sys.number()] : &_aux_soln;
1479 _sys_to_nonghost_and_ghost_soln.emplace(
1480 sys.number(),
1481 std::make_pair(nonghost_soln,
1482 NumericVector<Number>::build(nonghost_soln->comm()).release()));
1483 }
1484
1485 ConstNodeRange node_range(_ref_mesh.getMesh().nodes_begin(), _ref_mesh.getMesh().nodes_end());
1486
1487 for (auto & [sys_num, var_num_and_direction] : _sys_to_var_num_and_direction)
1488 {
1489 auto & sys = es.get_system(sys_num);
1490 AllNodesSendListThread send_list(
1491 this->_fe_problem, _ref_mesh, var_num_and_direction.first, sys);
1492 Threads::parallel_reduce(node_range, send_list, this->_fe_problem.numThreads());
1493 send_list.unique();
1494 auto & [soln, ghost_soln] = libmesh_map_find(_sys_to_nonghost_and_ghost_soln, sys_num);
1495 ghost_soln->init(
1496 soln->size(), soln->local_size(), send_list.send_list(), true, libMesh::GHOSTED);
1497 soln->localize(*ghost_soln, send_list.send_list());
1498 }
1499
1500 _has_displacement = false;
1501}
1502
1503void
1505{
1506 Node & displaced_node = *(*nd);
1507
1508 Node & reference_node = _ref_mesh.nodeRef(displaced_node.id());
1509
1510 for (auto & [sys_num, var_num_and_direction] : _sys_to_var_num_and_direction)
1511 {
1512 auto & var_numbers = var_num_and_direction.first;
1513 auto & directions = var_num_and_direction.second;
1514 for (const auto i : index_range(var_numbers))
1515 {
1516 const auto direction = directions[i];
1517 if (reference_node.n_dofs(sys_num, var_numbers[i]) > 0)
1518 {
1519 Real coord = reference_node(direction) +
1520 (*libmesh_map_find(_sys_to_nonghost_and_ghost_soln, sys_num).second)(
1521 reference_node.dof_number(sys_num, var_numbers[i], 0));
1522 // A non-finite displacement (e.g. after a failed linear solve) would corrupt every
1523 // downstream geometric operation. Throw so the solve can be stopped and the step cut.
1524 if (!std::isfinite(coord))
1525 throw MooseException("Non-finite displaced coordinate in direction ",
1526 direction,
1527 " at node ",
1528 displaced_node.id(),
1529 ".");
1530 if (displaced_node(direction) != coord)
1531 {
1532 displaced_node(direction) = coord;
1533 _has_displacement = true;
1534 }
1535 }
1536 }
1537 }
1538}
boundary_id_type BoundaryID
subdomain_id_type SubdomainID
registerMooseObject("MooseApp", DisplacedProblem)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
unsigned int TagID
Definition MooseTypes.h:238
unsigned int THREAD_ID
Definition MooseTypes.h:237
std::shared_ptr< DisplacedProblem > displaced_problem
void extraSendList(std::vector< dof_id_type > &send_list, void *context)
///< Type of coordinate system
Definition SystemBase.C:38
const std::vector< dof_id_type > & send_list() const
Key structure for APIs manipulating global vectors/matrices.
Definition Assembly.h:837
Keeps track of stuff related to assembling.
Definition Assembly.h:102
void setCurrentNeighborSubdomainID(SubdomainID i)
set the current subdomain ID
Definition Assembly.h:494
void setCurrentSubdomainID(SubdomainID i)
set the current subdomain ID
Definition Assembly.h:416
const NumericVector< Number > *const & currentSolution() const override
The solution vector that is currently being operated on.
void clearPoints()
Remove all of the current points and elements.
std::set< const Elem * > & getElements()
Returns a writeable reference to the _elements container.
MultiPointMap & getPoints()
Returns a writeable reference to the _points container.
void updatePointLocator(const MooseMesh &mesh)
Called during FEProblemBase::meshChanged() to update the PointLocator object used by the DiracKernels...
UpdateDisplacedMeshThread(FEProblemBase &fe_problem, DisplacedProblem &displaced_problem)
virtual void onNode(NodeRange::const_iterator &nd) override
bool hasDisplacement()
Whether the displaced mesh is modified by the latest call to operator()
virtual void addJacobianLowerD(const THREAD_ID tid) override
MooseMesh & refMesh()
virtual void clearDiracInfo() override
Gets called before Dirac Kernels are asked to add the points they are supposed to be evaluated in.
virtual std::pair< bool, unsigned int > determineSolverSystem(const std::string &var_name, bool error_if_not_found=false) const override
virtual LineSearch * getLineSearch() override
virtual unsigned int currentLinearSysNum() const override
virtual void addResidual(const THREAD_ID tid) override
std::vector< const NumericVector< Number > * > _nl_solution
The nonlinear system solutions.
virtual void ghostGhostedBoundaries() override
Causes the boundaries added using addGhostedBoundary to actually be ghosted.
virtual TagID getMatrixTagID(const TagName &tag_name) const override
Get a TagID from a TagName.
std::vector< std::unique_ptr< DisplacedSystem > > _displaced_solver_systems
void meshChanged(bool contract_mesh, bool clean_refinement_flags)
virtual void updateMesh(bool mesh_changing=false)
Copy the solutions on the undisplaced systems to the displaced systems and reinitialize the geometry ...
virtual bool checkNonlocalCouplingRequirement() const override
virtual void addAuxVariable(const std::string &var_type, const std::string &name, InputParameters &parameters)
virtual void addCachedResidualDirectly(NumericVector< Number > &residual, const THREAD_ID tid)
virtual void jacobianSetup() override
virtual void addResidualNeighbor(const THREAD_ID tid) override
virtual unsigned int solverSysNum(const SolverSystemName &sys_name) const override
virtual void reinitElemPhys(const Elem *elem, const std::vector< Point > &phys_points_in_elem, const THREAD_ID tid) override
virtual void addResidualLower(const THREAD_ID tid) override
virtual void getDiracElements(std::set< const Elem * > &elems) override
Fills "elems" with the elements that should be looped over for Dirac Kernels.
virtual bool isTransient() const override
virtual void addJacobian(const THREAD_ID tid) override
virtual unsigned int currentNlSysNum() const override
virtual bool matrixTagExists(const TagName &tag_name) const override
Check to see if a particular Tag exists.
virtual void initialSetup() override
virtual TagID getVectorTagID(const TagName &tag_name) const override
Get a TagID from a TagName.
virtual void reinitNodeFace(const Node *node, BoundaryID bnd_id, const THREAD_ID tid) override
EquationSystems _eq
void syncAuxSolution(const NumericVector< Number > &aux_soln)
Copy the provided solution into the displaced auxiliary system.
virtual void prepare(const Elem *elem, const THREAD_ID tid) override
virtual void prepareFace(const Elem *elem, const THREAD_ID tid) 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 void setResidual(NumericVector< Number > &residual, 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)
const NumericVector< Number > * _aux_solution
The auxiliary system solution.
virtual System & getSystem(const std::string &var_name) override
Returns the equation system containing the variable provided.
std::vector< std::vector< std::unique_ptr< Assembly > > > _assembly
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 bool safeAccessTaggedVectors() const override
Is it safe to access the tagged vectors.
virtual void prepareAssembly(const THREAD_ID tid) override
virtual void addGhostedBoundary(BoundaryID boundary_id) override
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
void undisplaceMesh()
Resets the displaced mesh to the reference mesh.
virtual void prepareAssemblyNeighbor(const THREAD_ID tid)
virtual bool vectorTagExists(const TagID tag_id) const override
Check to see if a particular Tag exists.
virtual void prepareShapes(unsigned int var, const THREAD_ID tid) override
virtual void addJacobianNeighborLowerD(const THREAD_ID tid) override
virtual const std::vector< VectorTag > & currentResidualVectorTags() const override
Return the residual vector tags we are currently computing.
virtual std::size_t numNonlinearSystems() const override
virtual void addJacobianNeighbor(const THREAD_ID tid) override
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.
MooseMesh & _ref_mesh
reference mesh
static InputParameters validParams()
virtual const VectorTag & getVectorTag(const TagID tag_id) const override
Get a VectorTag from a TagID.
virtual void cacheJacobianNonlocal(const THREAD_ID tid)
virtual void addVariable(const std::string &var_type, const std::string &name, InputParameters &parameters, unsigned int nl_system_number)
virtual void reinitElem(const Elem *elem, const THREAD_ID tid) override
virtual std::set< dof_id_type > & ghostedElems() override
Return the list of elements that should have their DoFs ghosted to this processor.
virtual unsigned int numMatrixTags() const override
The total number of tags.
virtual const CouplingMatrix * couplingMatrix(const unsigned int nl_sys_num) const override
The coupling matrix defining what blocks exist in the preconditioning matrix.
virtual void restoreOldSolutions()
Restore old solutions from the backup vectors and deallocate them.
void bumpAllQRuleOrder(Order order, SubdomainID block)
virtual Moose::VectorTagType vectorTagType(const TagID tag_id) const override
virtual void saveOldSolutions()
Allocate vectors and save old solutions into them.
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.
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 bool computingScalingResidual() const override final
Getter for whether we're computing the scaling residual.
virtual void init() override
virtual bool computingPreSMOResidual(const unsigned int nl_sys_num) const override
Returns true if the problem is in the process of computing it's initial residual.
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 bool hasScalarVariable(const std::string &var_name) const override
Returns a Boolean indicating whether any system contains a variable with the name provided.
virtual bool computingScalingJacobian() const override final
Getter for whether we're computing the scaling jacobian.
virtual void prepareNeighborShapes(unsigned int var, const THREAD_ID tid) override
virtual void customSetup(const ExecFlagType &exec_type) override
virtual void timestepSetup() override
virtual void onTimestepBegin() override
virtual bool safeAccessTaggedMatrices() const override
Is it safe to access the tagged matrices.
void addTimeIntegrator()
Get the time integrators from the problem.
std::unique_ptr< DisplacedSystem > _displaced_aux
virtual std::size_t numSolverSystems() 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 Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
virtual void setNeighborSubdomainID(const Elem *elem, unsigned int side, const THREAD_ID tid) override
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 void reinitElemNeighborAndLowerD(const Elem *elem, unsigned int side, const THREAD_ID tid) override
virtual void reinitNeighbor(const Elem *elem, unsigned int side, const THREAD_ID tid) override
virtual void addJacobianNonlocal(const THREAD_ID tid)
virtual void setResidualNeighbor(NumericVector< Number > &residual, const THREAD_ID tid) override
GeometricSearchData _geometric_search_data
virtual TagName vectorTagName(const TagID tag_id) const override
Retrieve the name associated with a TagID.
virtual std::size_t numLinearSystems() const override
FEProblemBase & _mproblem
virtual TagName matrixTagName(TagID tag) override
Retrieve the name associated with a TagID.
virtual bool hasNonlocalCoupling() const override
Whether the simulation has active nonlocal coupling which should be accounted for in the Jacobian.
DisplacedProblem(DisplacedProblem &&)=delete
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.
bool haveADObjects() const
Method for reading wehther we have any ad objects.
Definition SubProblem.h:782
virtual void reinitElemFace(const Elem *elem, unsigned int side, const THREAD_ID tid) override
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 solverSystemConverged(const unsigned int solver_sys_num) override
virtual bool hasVariable(const std::string &var_name) const override
Whether or not this problem has the variable.
void bumpVolumeQRuleOrder(Order order, SubdomainID block)
virtual const libMesh::CouplingMatrix & nonlocalCouplingMatrix(const unsigned i) const override
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL) override
Create a Tag.
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid) override
virtual void updateGeomSearch(GeometricSearchData::GeometricSearchType type=GeometricSearchData::ALL) override
update geometric search data
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.
virtual void residualSetup() override
virtual void reinitNeighborPhys(const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > &physical_points, const THREAD_ID tid) override
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...
virtual EquationSystems & es() override
virtual void prepareNonlocal(const THREAD_ID tid)
virtual void needFV() override
marks this problem as including/needing finite volume functionality.
virtual bool haveFV() const override
returns true if this problem includes/needs finite volume functionality.
virtual void reinitNode(const Node *node, const THREAD_ID tid) override
virtual void prepareFaceShapes(unsigned int var, const THREAD_ID tid) override
virtual TagID addMatrixTag(TagName tag_name) override
Create a Tag.
virtual unsigned int linearSysNum(const LinearSystemName &sys_name) const override
virtual void onTimestepEnd() 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.
std::vector< std::string > _displacements
virtual void reinitOffDiagScalars(const THREAD_ID tid) override
virtual void initAdaptivity()
virtual void createQRules(QuadratureType type, Order order, Order volume_order, Order face_order, SubdomainID block, bool allow_negative_qweights=true)
void syncSolutions()
Copy the solutions on the undisplaced systems to the displaced systems.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
bool hasJacobian() const
Returns _has_jacobian.
virtual std::size_t numLinearSystems() const override
virtual bool haveFV() const override
returns true if this problem includes/needs finite volume functionality.
virtual unsigned int currentLinearSysNum() const override
AuxiliarySystem & getAuxiliarySystem()
virtual const libMesh::CouplingMatrix & nonlocalCouplingMatrix(const unsigned i) const override
virtual std::size_t numSolverSystems() const 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.
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 std::size_t numNonlinearSystems() const override
virtual const std::vector< VectorTag > & currentResidualVectorTags() const override
Return the residual vector tags we are currently computing.
LineSearch * getLineSearch() override
getter for the MOOSE line search
virtual void needFV() override
marks this problem as including/needing finite volume functionality.
void computingScalingJacobian(bool computing_scaling_jacobian)
Setter for whether we're computing the scaling jacobian.
unsigned int solverSysNum(const SolverSystemName &solver_sys_name) const override
unsigned int linearSysNum(const LinearSystemName &linear_sys_name) const override
const libMesh::CouplingMatrix * couplingMatrix(const unsigned int nl_sys_num) const override
The coupling matrix defining what blocks exist in the preconditioning matrix.
virtual void addGhostedBoundary(BoundaryID boundary_id) override
Will make sure that all necessary elements from boundary_id are ghosted to this processor.
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 unsigned int currentNlSysNum() const override
virtual unsigned int nlSysNum(const NonlinearSystemName &nl_sys_name) const override
virtual bool checkNonlocalCouplingRequirement() const override
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
void automaticScaling(bool automatic_scaling) override
Automatic scaling setter.
virtual void meshDisplaced()
Update data after a mesh displaced.
virtual bool isTransient() const override
void computingScalingResidual(bool computing_scaling_residual)
Setter for whether we're computing the scaling residual.
virtual void ghostGhostedBoundaries() override
Causes the boundaries added using addGhostedBoundary to actually be ghosted.
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 bool computingPreSMOResidual(const unsigned int nl_sys_num) const override
Returns true if the problem is in the process of computing it's initial residual.
bool constJacobian() const
Returns _const_jacobian (whether a MOOSE object has specified that the Jacobian is the same as the pr...
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Definition FEProblem.h:21
void reinit()
Completely redo all geometric search objects.
GeometricSearchType
Used to select groups of geometric search objects to update.
void update(GeometricSearchType type=ALL)
Update all of the search objects.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
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...
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.
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
const std::string & type() const
Get the type of this class.
Definition MooseBase.h:93
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
Class for containing MooseEnum item information.
Provides a way for users to bail out of the current solve.
virtual const char * what() const
Get out the error message.
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
void setupFiniteVolumeMeshData() const
Sets up the additional data needed for finite volume computations.
Definition MooseMesh.C:4156
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:1648
void meshChanged()
Declares that the MooseMesh has changed, invalidates cached data and rebuilds caches.
Definition MooseMesh.C:894
virtual const Node & nodeRef(const dof_id_type i) const
Definition MooseMesh.C:846
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3512
void setCoordData(const MooseMesh &other_mesh)
Set the coordinate system data to that of other_mesh.
Definition MooseMesh.C:4406
void clearQuadratureNodes()
Clear out any existing quadrature nodes.
Definition MooseMesh.C:1625
virtual Elem * queryElemPtr(const dof_id_type i)
Definition MooseMesh.C:3189
const std::set< SubdomainID > & interiorLowerDBlocks() const
Definition MooseMesh.h:1550
This class provides an interface for common operations on field variables of both FE and FV types wit...
Class for scalar variables (they are different).
Generic class for solving transient nonlinear problems.
Definition SubProblem.h:79
THREAD_ID numThreads() const
Definition SubProblem.C:81
virtual TagName vectorTagName(const TagID tag) const
Retrieve the name associated with a TagID.
Definition SubProblem.C:213
virtual TagID getVectorTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition SubProblem.C:195
virtual Moose::VectorTagType vectorTagType(const TagID tag_id) const
Definition SubProblem.C:223
virtual const VectorTag & getVectorTag(const TagID tag_id) const
Get a VectorTag from a TagID.
Definition SubProblem.C:153
virtual bool safeAccessTaggedMatrices() const
Is it safe to access the tagged matrices.
Definition SubProblem.h:742
virtual void customSetup(const ExecFlagType &exec_type)
virtual void jacobianSetup()
virtual void initialSetup()
virtual std::set< dof_id_type > & ghostedElems()
Return the list of elements that should have their DoFs ghosted to this processor.
Definition SubProblem.h:683
std::vector< VectorTag > getVectorTags(const std::set< TagID > &tag_ids) const
Definition SubProblem.C:164
virtual unsigned int numMatrixTags() const
The total number of tags.
Definition SubProblem.h:251
static InputParameters validParams()
Definition SubProblem.C:34
virtual TagID getMatrixTagID(const TagName &tag_name) const
Get a TagID from a TagName.
Definition SubProblem.C:334
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:187
virtual TagName matrixTagName(TagID tag)
Retrieve the name associated with a TagID.
Definition SubProblem.C:349
DiracKernelInfo _dirac_kernel_info
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition SubProblem.C:84
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:116
virtual bool matrixTagExists(const TagName &tag_name) const
Check to see if a particular Tag exists.
Definition SubProblem.C:320
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 bool safeAccessTaggedVectors() const
Is it safe to access the tagged vectors.
Definition SubProblem.h:745
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Definition SubProblem.C:303
virtual void timestepSetup()
virtual bool vectorTagExists(const TagID tag_id) const
Check to see if a particular Tag exists.
Definition SubProblem.h:204
virtual void residualSetup()
bool _have_ad_objects
AD flag indicating whether any AD objects have been added.
bool automaticScaling() const
Automatic scaling getter.
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:949
virtual const std::string & name() const
void update()
Update the system (doing libMesh magic)
Storage for all of the information pretaining to a vector tag.
Definition VectorTag.h:18
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
MeshBase & mesh
VarKindType
Framework-wide stuff.
Definition MooseTypes.h:769
@ VAR_AUXILIARY
Definition MooseTypes.h:771
@ VAR_SOLVER
Definition MooseTypes.h:770
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())