https://mooseframework.inl.gov
NonlinearSystemBase.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 #include "NonlinearSystemBase.h"
11 #include "AuxiliarySystem.h"
12 #include "Problem.h"
13 #include "FEProblem.h"
14 #include "MooseVariableFE.h"
15 #include "MooseVariableScalar.h"
16 #include "PetscSupport.h"
17 #include "Factory.h"
18 #include "ParallelUniqueId.h"
19 #include "ThreadedElementLoop.h"
20 #include "MaterialData.h"
21 #include "ComputeResidualThread.h"
23 #include "ComputeFVFluxThread.h"
24 #include "ComputeJacobianThread.h"
28 #include "ComputeDiracThread.h"
35 #include "TimeKernel.h"
36 #include "BoundaryCondition.h"
37 #include "DirichletBCBase.h"
38 #include "NodalBCBase.h"
39 #include "IntegratedBCBase.h"
40 #include "DGKernel.h"
41 #include "InterfaceKernelBase.h"
42 #include "ElementDamper.h"
43 #include "NodalDamper.h"
44 #include "GeneralDamper.h"
45 #include "DisplacedProblem.h"
46 #include "NearestNodeLocator.h"
47 #include "PenetrationLocator.h"
48 #include "NodalConstraint.h"
49 #include "NodeFaceConstraint.h"
50 #include "NodeElemConstraintBase.h"
51 #include "MortarConstraint.h"
52 #include "ElemElemConstraint.h"
53 #include "ScalarKernelBase.h"
54 #include "Parser.h"
55 #include "Split.h"
57 #include "MooseMesh.h"
58 #include "MooseUtils.h"
59 #include "MooseApp.h"
60 #include "NodalKernelBase.h"
61 #include "DiracKernelBase.h"
62 #include "TimeIntegrator.h"
63 #include "Predictor.h"
64 #include "Assembly.h"
65 #include "ElementPairLocator.h"
66 #include "ODETimeKernel.h"
69 #include "ADKernel.h"
70 #include "ADDirichletBCBase.h"
71 #include "Moose.h"
72 #include "ConsoleStream.h"
73 #include "MooseError.h"
74 #include "FVElementalKernel.h"
77 #include "FVFluxKernel.h"
79 #include "UserObject.h"
81 #include "HDGKernel.h"
82 
83 // libMesh
84 #include "libmesh/nonlinear_solver.h"
85 #include "libmesh/quadrature_gauss.h"
86 #include "libmesh/dense_vector.h"
87 #include "libmesh/boundary_info.h"
88 #include "libmesh/petsc_matrix.h"
89 #include "libmesh/petsc_vector.h"
90 #include "libmesh/petsc_nonlinear_solver.h"
91 #include "libmesh/numeric_vector.h"
92 #include "libmesh/mesh.h"
93 #include "libmesh/dense_subvector.h"
94 #include "libmesh/dense_submatrix.h"
95 #include "libmesh/dof_map.h"
96 #include "libmesh/sparse_matrix.h"
97 #include "libmesh/petsc_matrix.h"
98 #include "libmesh/default_coupling.h"
99 #include "libmesh/diagonal_matrix.h"
100 #include "libmesh/fe_interface.h"
101 #include "libmesh/petsc_solver_exception.h"
102 
103 #include <ios>
104 
105 #include "petscsnes.h"
106 #include <PetscDMMoose.h>
107 EXTERN_C_BEGIN
108 extern PetscErrorCode DMCreate_Moose(DM);
109 EXTERN_C_END
110 
111 using namespace libMesh;
112 
114  System & sys,
115  const std::string & name)
116  : SolverSystem(fe_problem, fe_problem, name, Moose::VAR_SOLVER),
117  PerfGraphInterface(fe_problem.getMooseApp().perfGraph(), "NonlinearSystemBase"),
118  _sys(sys),
119  _last_nl_rnorm(0.),
120  _current_nl_its(0),
121  _residual_ghosted(NULL),
122  _Re_time_tag(-1),
123  _Re_time(NULL),
124  _Re_non_time_tag(-1),
125  _Re_non_time(NULL),
126  _scalar_kernels(/*threaded=*/false),
127  _nodal_bcs(/*threaded=*/false),
128  _preset_nodal_bcs(/*threaded=*/false),
129  _ad_preset_nodal_bcs(/*threaded=*/false),
130  _splits(/*threaded=*/false),
131  _increment_vec(NULL),
132  _use_finite_differenced_preconditioner(false),
133  _fdcoloring(nullptr),
134  _fsp(nullptr),
135  _add_implicit_geometric_coupling_entries_to_jacobian(false),
136  _assemble_constraints_separately(false),
137  _need_residual_ghosted(false),
138  _debugging_residuals(false),
139  _doing_dg(false),
140  _n_iters(0),
141  _n_linear_iters(0),
142  _n_residual_evaluations(0),
143  _final_residual(0.),
144  _computing_pre_smo_residual(false),
145  _pre_smo_residual(0),
146  _initial_residual(0),
147  _use_pre_smo_residual(false),
148  _print_all_var_norms(false),
149  _has_save_in(false),
150  _has_diag_save_in(false),
151  _has_nodalbc_save_in(false),
152  _has_nodalbc_diag_save_in(false),
153  _computed_scaling(false),
154  _compute_scaling_once(true),
155  _resid_vs_jac_scaling_param(0),
156  _off_diagonals_in_auto_scaling(false),
157  _auto_scaling_initd(false)
158 {
160  // Don't need to add the matrix - it already exists (for now)
162 
163  // The time matrix tag is not normally used - but must be added to the system
164  // in case it is so that objects can have 'time' in their matrix tags by default
165  _fe_problem.addMatrixTag("TIME");
166 
167  _Re_tag = _fe_problem.addVectorTag("RESIDUAL");
168 
170 
172  {
173  auto & dof_map = _sys.get_dof_map();
174  dof_map.remove_algebraic_ghosting_functor(dof_map.default_algebraic_ghosting());
175  dof_map.set_implicit_neighbor_dofs(false);
176  }
177 }
178 
180 
181 void
183 {
185 
186  if (_fe_problem.hasDampers())
187  setupDampers();
188 
189  if (_residual_copy.get())
190  _residual_copy->init(_sys.n_dofs(), false, SERIAL);
191 }
192 
193 void
195 {
196  // reinit is called on meshChanged() in FEProblemBase. We could implement meshChanged() instead.
197  // Subdomains might have changed
198  for (auto & functor : _displaced_mortar_functors)
199  functor.second.setupMortarMaterials();
200  for (auto & functor : _undisplaced_mortar_functors)
201  functor.second.setupMortarMaterials();
202 }
203 
204 void
206 {
208  nonlinearSolver()->jacobian = NULL;
209 }
210 
211 void
213 {
214  TIME_SECTION("nlInitialSetup", 2, "Setting Up Nonlinear System");
215 
217 
218  {
219  TIME_SECTION("kernelsInitialSetup", 2, "Setting Up Kernels/BCs/Constraints");
220 
221  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
222  {
223  _kernels.initialSetup(tid);
226  if (_doing_dg)
229 
233 
234  if (_fe_problem.haveFV())
235  {
236  std::vector<FVElementalKernel *> fv_elemental_kernels;
238  .query()
239  .template condition<AttribSystem>("FVElementalKernel")
240  .template condition<AttribThread>(tid)
241  .queryInto(fv_elemental_kernels);
242 
243  for (auto * fv_kernel : fv_elemental_kernels)
244  fv_kernel->initialSetup();
245 
246  std::vector<FVFluxKernel *> fv_flux_kernels;
248  .query()
249  .template condition<AttribSystem>("FVFluxKernel")
250  .template condition<AttribThread>(tid)
251  .queryInto(fv_flux_kernels);
252 
253  for (auto * fv_kernel : fv_flux_kernels)
254  fv_kernel->initialSetup();
255  }
256  }
257 
262  }
263 
264  {
265  TIME_SECTION("mortarSetup", 2, "Initializing Mortar Interfaces");
266 
267  auto create_mortar_functors = [this](const bool displaced)
268  {
269  // go over mortar interfaces and construct functors
270  const auto & mortar_interfaces = _fe_problem.getMortarInterfaces(displaced);
271  for (const auto & mortar_interface : mortar_interfaces)
272  {
273  const auto primary_secondary_boundary_pair = mortar_interface.first;
274  if (!_constraints.hasActiveMortarConstraints(primary_secondary_boundary_pair, displaced))
275  continue;
276 
277  const auto & mortar_generation_object = mortar_interface.second;
278 
279  auto & mortar_constraints =
280  _constraints.getActiveMortarConstraints(primary_secondary_boundary_pair, displaced);
281 
282  auto & subproblem = displaced
283  ? static_cast<SubProblem &>(*_fe_problem.getDisplacedProblem())
284  : static_cast<SubProblem &>(_fe_problem);
285 
286  auto & mortar_functors =
288 
289  mortar_functors.emplace(primary_secondary_boundary_pair,
290  ComputeMortarFunctor(mortar_constraints,
291  mortar_generation_object,
292  subproblem,
293  _fe_problem,
294  displaced,
295  subproblem.assembly(0, number())));
296  }
297  };
298 
299  create_mortar_functors(false);
300  create_mortar_functors(true);
301  }
302 
303  if (_automatic_scaling)
304  {
306  _scaling_matrix = std::make_unique<OffDiagonalScalingMatrix<Number>>(_communicator);
307  else
308  _scaling_matrix = std::make_unique<DiagonalMatrix<Number>>(_communicator);
309  }
310 
311  if (_preconditioner)
312  _preconditioner->initialSetup();
313 }
314 
315 void
317 {
319 
320  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
321  {
322  _kernels.timestepSetup(tid);
325  if (_doing_dg)
331 
332  if (_fe_problem.haveFV())
333  {
334  std::vector<FVFluxBC *> bcs;
336  .query()
337  .template condition<AttribSystem>("FVFluxBC")
338  .template condition<AttribThread>(tid)
339  .queryInto(bcs);
340 
341  std::vector<FVInterfaceKernel *> iks;
343  .query()
344  .template condition<AttribSystem>("FVInterfaceKernel")
345  .template condition<AttribThread>(tid)
346  .queryInto(iks);
347 
348  std::vector<FVFluxKernel *> kernels;
350  .query()
351  .template condition<AttribSystem>("FVFluxKernel")
352  .template condition<AttribThread>(tid)
353  .queryInto(kernels);
354 
355  for (auto * bc : bcs)
356  bc->timestepSetup();
357  for (auto * ik : iks)
358  ik->timestepSetup();
359  for (auto * kernel : kernels)
360  kernel->timestepSetup();
361  }
362  }
367 }
368 
369 void
371 {
372  SolverSystem::customSetup(exec_type);
373 
374  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
375  {
376  _kernels.customSetup(exec_type, tid);
377  _nodal_kernels.customSetup(exec_type, tid);
378  _dirac_kernels.customSetup(exec_type, tid);
379  if (_doing_dg)
380  _dg_kernels.customSetup(exec_type, tid);
381  _interface_kernels.customSetup(exec_type, tid);
382  _element_dampers.customSetup(exec_type, tid);
383  _nodal_dampers.customSetup(exec_type, tid);
384  _integrated_bcs.customSetup(exec_type, tid);
385 
386  if (_fe_problem.haveFV())
387  {
388  std::vector<FVFluxBC *> bcs;
390  .query()
391  .template condition<AttribSystem>("FVFluxBC")
392  .template condition<AttribThread>(tid)
393  .queryInto(bcs);
394 
395  std::vector<FVInterfaceKernel *> iks;
397  .query()
398  .template condition<AttribSystem>("FVInterfaceKernel")
399  .template condition<AttribThread>(tid)
400  .queryInto(iks);
401 
402  std::vector<FVFluxKernel *> kernels;
404  .query()
405  .template condition<AttribSystem>("FVFluxKernel")
406  .template condition<AttribThread>(tid)
407  .queryInto(kernels);
408 
409  for (auto * bc : bcs)
410  bc->customSetup(exec_type);
411  for (auto * ik : iks)
412  ik->customSetup(exec_type);
413  for (auto * kernel : kernels)
414  kernel->customSetup(exec_type);
415  }
416  }
417  _scalar_kernels.customSetup(exec_type);
418  _constraints.customSetup(exec_type);
419  _general_dampers.customSetup(exec_type);
420  _nodal_bcs.customSetup(exec_type);
421 }
422 
423 void
425 {
426  if (_fsp)
427  _fsp->setupDM();
428 }
429 
430 void
431 NonlinearSystemBase::addKernel(const std::string & kernel_name,
432  const std::string & name,
433  InputParameters & parameters)
434 {
435  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
436  {
437  // Create the kernel object via the factory and add to warehouse
438  std::shared_ptr<KernelBase> kernel =
439  _factory.create<KernelBase>(kernel_name, name, parameters, tid);
440  _kernels.addObject(kernel, tid);
441  postAddResidualObject(*kernel);
442  // Add to theWarehouse, a centralized storage for all moose objects
443  _fe_problem.theWarehouse().add(kernel);
444  }
445 
446  if (parameters.get<std::vector<AuxVariableName>>("save_in").size() > 0)
447  _has_save_in = true;
448  if (parameters.get<std::vector<AuxVariableName>>("diag_save_in").size() > 0)
449  _has_diag_save_in = true;
450 }
451 
452 void
453 NonlinearSystemBase::addHDGKernel(const std::string & kernel_name,
454  const std::string & name,
455  InputParameters & parameters)
456 {
457  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
458  {
459  // Create the kernel object via the factory and add to warehouse
460  auto kernel = _factory.create<HDGKernel>(kernel_name, name, parameters, tid);
461  _kernels.addObject(kernel, tid);
462  _hybridized_kernels.addObject(kernel, tid);
463  // Add to theWarehouse, a centralized storage for all moose objects
464  _fe_problem.theWarehouse().add(kernel);
465  postAddResidualObject(*kernel);
466  }
467 }
468 
469 void
470 NonlinearSystemBase::addNodalKernel(const std::string & kernel_name,
471  const std::string & name,
472  InputParameters & parameters)
473 {
474  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
475  {
476  // Create the kernel object via the factory and add to the warehouse
477  std::shared_ptr<NodalKernelBase> kernel =
478  _factory.create<NodalKernelBase>(kernel_name, name, parameters, tid);
479  _nodal_kernels.addObject(kernel, tid);
480  // Add to theWarehouse, a centralized storage for all moose objects
481  _fe_problem.theWarehouse().add(kernel);
482  postAddResidualObject(*kernel);
483  }
484 
485  if (parameters.get<std::vector<AuxVariableName>>("save_in").size() > 0)
486  _has_save_in = true;
487  if (parameters.get<std::vector<AuxVariableName>>("diag_save_in").size() > 0)
488  _has_diag_save_in = true;
489 }
490 
491 void
492 NonlinearSystemBase::addScalarKernel(const std::string & kernel_name,
493  const std::string & name,
494  InputParameters & parameters)
495 {
496  std::shared_ptr<ScalarKernelBase> kernel =
497  _factory.create<ScalarKernelBase>(kernel_name, name, parameters);
498  postAddResidualObject(*kernel);
499  // Add to theWarehouse, a centralized storage for all moose objects
500  _fe_problem.theWarehouse().add(kernel);
501  _scalar_kernels.addObject(kernel);
502 }
503 
504 void
505 NonlinearSystemBase::addBoundaryCondition(const std::string & bc_name,
506  const std::string & name,
507  InputParameters & parameters)
508 {
509  // ThreadID
510  THREAD_ID tid = 0;
511 
512  // Create the object
513  std::shared_ptr<BoundaryCondition> bc =
514  _factory.create<BoundaryCondition>(bc_name, name, parameters, tid);
516 
517  // Active BoundaryIDs for the object
518  const std::set<BoundaryID> & boundary_ids = bc->boundaryIDs();
519  auto bc_var = dynamic_cast<const MooseVariableFieldBase *>(&bc->variable());
520  _vars[tid].addBoundaryVar(boundary_ids, bc_var);
521 
522  // Cast to the various types of BCs
523  std::shared_ptr<NodalBCBase> nbc = std::dynamic_pointer_cast<NodalBCBase>(bc);
524  std::shared_ptr<IntegratedBCBase> ibc = std::dynamic_pointer_cast<IntegratedBCBase>(bc);
525 
526  // NodalBCBase
527  if (nbc)
528  {
529  if (nbc->checkNodalVar() && !nbc->variable().isNodal())
530  mooseError("Trying to use nodal boundary condition '",
531  nbc->name(),
532  "' on a non-nodal variable '",
533  nbc->variable().name(),
534  "'.");
535 
536  _nodal_bcs.addObject(nbc);
537  // Add to theWarehouse, a centralized storage for all moose objects
539  _vars[tid].addBoundaryVars(boundary_ids, nbc->getCoupledVars());
540 
541  if (parameters.get<std::vector<AuxVariableName>>("save_in").size() > 0)
542  _has_nodalbc_save_in = true;
543  if (parameters.get<std::vector<AuxVariableName>>("diag_save_in").size() > 0)
545 
546  // DirichletBCs that are preset
547  std::shared_ptr<DirichletBCBase> dbc = std::dynamic_pointer_cast<DirichletBCBase>(bc);
548  if (dbc && dbc->preset())
550 
551  std::shared_ptr<ADDirichletBCBase> addbc = std::dynamic_pointer_cast<ADDirichletBCBase>(bc);
552  if (addbc && addbc->preset())
554  }
555 
556  // IntegratedBCBase
557  else if (ibc)
558  {
559  _integrated_bcs.addObject(ibc, tid);
560  // Add to theWarehouse, a centralized storage for all moose objects
562  _vars[tid].addBoundaryVars(boundary_ids, ibc->getCoupledVars());
563 
564  if (parameters.get<std::vector<AuxVariableName>>("save_in").size() > 0)
565  _has_save_in = true;
566  if (parameters.get<std::vector<AuxVariableName>>("diag_save_in").size() > 0)
567  _has_diag_save_in = true;
568 
569  for (tid = 1; tid < libMesh::n_threads(); tid++)
570  {
571  // Create the object
572  bc = _factory.create<BoundaryCondition>(bc_name, name, parameters, tid);
573 
574  // Give users opportunity to set some parameters
576 
577  // Active BoundaryIDs for the object
578  const std::set<BoundaryID> & boundary_ids = bc->boundaryIDs();
579  _vars[tid].addBoundaryVar(boundary_ids, bc_var);
580 
581  ibc = std::static_pointer_cast<IntegratedBCBase>(bc);
582 
583  _integrated_bcs.addObject(ibc, tid);
584  _vars[tid].addBoundaryVars(boundary_ids, ibc->getCoupledVars());
585  }
586  }
587 
588  else
589  mooseError("Unknown BoundaryCondition type for object named ", bc->name());
590 }
591 
592 void
593 NonlinearSystemBase::addConstraint(const std::string & c_name,
594  const std::string & name,
595  InputParameters & parameters)
596 {
597  std::shared_ptr<Constraint> constraint = _factory.create<Constraint>(c_name, name, parameters);
598  _constraints.addObject(constraint);
599  postAddResidualObject(*constraint);
600 
601  if (constraint && constraint->addCouplingEntriesToJacobian())
603 }
604 
605 void
606 NonlinearSystemBase::addDiracKernel(const std::string & kernel_name,
607  const std::string & name,
608  InputParameters & parameters)
609 {
610  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
611  {
612  std::shared_ptr<DiracKernelBase> kernel =
613  _factory.create<DiracKernelBase>(kernel_name, name, parameters, tid);
614  postAddResidualObject(*kernel);
615  _dirac_kernels.addObject(kernel, tid);
616  // Add to theWarehouse, a centralized storage for all moose objects
617  _fe_problem.theWarehouse().add(kernel);
618  }
619 }
620 
621 void
622 NonlinearSystemBase::addDGKernel(std::string dg_kernel_name,
623  const std::string & name,
624  InputParameters & parameters)
625 {
626  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
627  {
628  auto dg_kernel = _factory.create<DGKernelBase>(dg_kernel_name, name, parameters, tid);
629  _dg_kernels.addObject(dg_kernel, tid);
630  // Add to theWarehouse, a centralized storage for all moose objects
631  _fe_problem.theWarehouse().add(dg_kernel);
632  postAddResidualObject(*dg_kernel);
633  }
634 
635  _doing_dg = true;
636 
637  if (parameters.get<std::vector<AuxVariableName>>("save_in").size() > 0)
638  _has_save_in = true;
639  if (parameters.get<std::vector<AuxVariableName>>("diag_save_in").size() > 0)
640  _has_diag_save_in = true;
641 }
642 
643 void
644 NonlinearSystemBase::addInterfaceKernel(std::string interface_kernel_name,
645  const std::string & name,
646  InputParameters & parameters)
647 {
648  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
649  {
650  std::shared_ptr<InterfaceKernelBase> interface_kernel =
651  _factory.create<InterfaceKernelBase>(interface_kernel_name, name, parameters, tid);
652  postAddResidualObject(*interface_kernel);
653 
654  const std::set<BoundaryID> & boundary_ids = interface_kernel->boundaryIDs();
655  auto ik_var = dynamic_cast<const MooseVariableFieldBase *>(&interface_kernel->variable());
656  _vars[tid].addBoundaryVar(boundary_ids, ik_var);
657 
658  _interface_kernels.addObject(interface_kernel, tid);
659  // Add to theWarehouse, a centralized storage for all moose objects
660  _fe_problem.theWarehouse().add(interface_kernel);
661  _vars[tid].addBoundaryVars(boundary_ids, interface_kernel->getCoupledVars());
662  }
663 }
664 
665 void
666 NonlinearSystemBase::addDamper(const std::string & damper_name,
667  const std::string & name,
668  InputParameters & parameters)
669 {
670  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
671  {
672  std::shared_ptr<Damper> damper = _factory.create<Damper>(damper_name, name, parameters, tid);
673 
674  // Attempt to cast to the damper types
675  std::shared_ptr<ElementDamper> ed = std::dynamic_pointer_cast<ElementDamper>(damper);
676  std::shared_ptr<NodalDamper> nd = std::dynamic_pointer_cast<NodalDamper>(damper);
677  std::shared_ptr<GeneralDamper> gd = std::dynamic_pointer_cast<GeneralDamper>(damper);
678 
679  if (gd)
680  {
682  break; // not threaded
683  }
684  else if (ed)
685  _element_dampers.addObject(ed, tid);
686  else if (nd)
687  _nodal_dampers.addObject(nd, tid);
688  else
689  mooseError("Invalid damper type");
690  }
691 }
692 
693 void
694 NonlinearSystemBase::addSplit(const std::string & split_name,
695  const std::string & name,
696  InputParameters & parameters)
697 {
698  std::shared_ptr<Split> split = _factory.create<Split>(split_name, name, parameters);
700  // Add to theWarehouse, a centralized storage for all moose objects
702 }
703 
704 std::shared_ptr<Split>
705 NonlinearSystemBase::getSplit(const std::string & name)
706 {
707  return _splits.getActiveObject(name);
708 }
709 
710 bool
712 {
714  return false;
715 
716  // The legacy behavior (#10464) _always_ performs the pre-SMO residual evaluation
717  // regardless of whether it is needed.
718  //
719  // This is not ideal and has been fixed by #23472. This legacy option ensures a smooth transition
720  // to the new behavior. Modules and Apps that want to migrate to the new behavior should set this
721  // parameter to false.
722  if (_app.parameters().get<bool>("use_legacy_initial_residual_evaluation_behavior"))
723  return true;
724 
725  return _use_pre_smo_residual;
726 }
727 
728 Real
730 {
732 }
733 
734 Real
736 {
738  mooseError("pre-SMO residual is requested but not evaluated.");
739 
740  return _pre_smo_residual;
741 }
742 
743 Real
745 {
746  return _initial_residual;
747 }
748 
749 void
751 {
752  _initial_residual = r;
753 }
754 
755 void
756 NonlinearSystemBase::zeroVectorForResidual(const std::string & vector_name)
757 {
758  for (unsigned int i = 0; i < _vecs_to_zero_for_residual.size(); ++i)
759  if (vector_name == _vecs_to_zero_for_residual[i])
760  return;
761 
762  _vecs_to_zero_for_residual.push_back(vector_name);
763 }
764 
765 void
767 {
768  _nl_vector_tags.clear();
769  _nl_vector_tags.insert(tag_id);
771 
773 
775 
777 }
778 
779 void
781 {
782  mooseDeprecated(" Please use computeResidualTag");
783 
784  computeResidualTag(residual, tag_id);
785 }
786 
787 void
788 NonlinearSystemBase::computeResidualTags(const std::set<TagID> & tags)
789 {
790  parallel_object_only();
791 
792  TIME_SECTION("nl::computeResidualTags", 5);
793 
796 
797  bool required_residual = tags.find(residualVectorTag()) == tags.end() ? false : true;
798 
800 
801  // not suppose to do anythin on matrix
803 
805 
806  for (const auto & numeric_vec : _vecs_to_zero_for_residual)
807  if (hasVector(numeric_vec))
808  {
809  NumericVector<Number> & vec = getVector(numeric_vec);
810  vec.close();
811  vec.zero();
812  }
813 
814  try
815  {
816  zeroTaggedVectors(tags);
818  closeTaggedVectors(tags);
819 
820  if (required_residual)
821  {
822  auto & residual = getVector(residualVectorTag());
823  if (!_time_integrators.empty())
824  {
825  for (auto & ti : _time_integrators)
826  ti->postResidual(residual);
827  }
828  else
829  residual += *_Re_non_time;
830  residual.close();
831  }
833  // We don't want to do nodal bcs or anything else
834  return;
835 
836  computeNodalBCs(tags);
837  closeTaggedVectors(tags);
838 
839  // If we are debugging residuals we need one more assignment to have the ghosted copy up to
840  // date
841  if (_need_residual_ghosted && _debugging_residuals && required_residual)
842  {
843  auto & residual = getVector(residualVectorTag());
844 
845  *_residual_ghosted = residual;
847  }
848  // Need to close and update the aux system in case residuals were saved to it.
851  if (hasSaveIn())
853  }
854  catch (MooseException & e)
855  {
856  // The buck stops here, we have already handled the exception by
857  // calling stopSolve(), it is now up to PETSc to return a
858  // "diverged" reason during the next solve.
859  }
860 
861  // not supposed to do anything on matrix
863 
865 }
866 
867 void
868 NonlinearSystemBase::computeResidualAndJacobianTags(const std::set<TagID> & vector_tags,
869  const std::set<TagID> & matrix_tags)
870 {
871  const bool required_residual =
872  vector_tags.find(residualVectorTag()) == vector_tags.end() ? false : true;
873 
874  try
875  {
876  zeroTaggedVectors(vector_tags);
877  computeResidualAndJacobianInternal(vector_tags, matrix_tags);
878  closeTaggedVectors(vector_tags);
879  closeTaggedMatrices(matrix_tags);
880 
881  if (required_residual)
882  {
883  auto & residual = getVector(residualVectorTag());
884  if (!_time_integrators.empty())
885  {
886  for (auto & ti : _time_integrators)
887  ti->postResidual(residual);
888  }
889  else
890  residual += *_Re_non_time;
891  residual.close();
892  }
893 
895  closeTaggedVectors(vector_tags);
896  closeTaggedMatrices(matrix_tags);
897  }
898  catch (MooseException & e)
899  {
900  // The buck stops here, we have already handled the exception by
901  // calling stopSolve(), it is now up to PETSc to return a
902  // "diverged" reason during the next solve.
903  }
904 }
905 
906 void
908 {
909  for (auto & ti : _time_integrators)
910  ti->preSolve();
911  if (_predictor.get())
912  _predictor->timestepSetup();
913 }
914 
915 void
917 {
919 
920  NumericVector<Number> & initial_solution(solution());
921  if (_predictor.get())
922  {
923  if (_predictor->shouldApply())
924  {
925  TIME_SECTION("applyPredictor", 2, "Applying Predictor");
926 
927  _predictor->apply(initial_solution);
928  _fe_problem.predictorCleanup(initial_solution);
929  }
930  else
931  _console << " Skipping predictor this step" << std::endl;
932  }
933 
934  // do nodal BC
935  {
936  TIME_SECTION("initialBCs", 2, "Applying BCs To Initial Condition");
937 
939  for (const auto & bnode : bnd_nodes)
940  {
941  BoundaryID boundary_id = bnode->_bnd_id;
942  Node * node = bnode->_node;
943 
944  if (node->processor_id() == processor_id())
945  {
946  // reinit variables in nodes
947  _fe_problem.reinitNodeFace(node, boundary_id, 0);
948 
950  {
951  const auto & preset_bcs = _preset_nodal_bcs.getActiveBoundaryObjects(boundary_id);
952  for (const auto & preset_bc : preset_bcs)
953  preset_bc->computeValue(initial_solution);
954  }
956  {
957  const auto & preset_bcs_res = _ad_preset_nodal_bcs.getActiveBoundaryObjects(boundary_id);
958  for (const auto & preset_bc : preset_bcs_res)
959  preset_bc->computeValue(initial_solution);
960  }
961  }
962  }
963  }
964 
965  _sys.solution->close();
966  update();
967 
968  // Set constraint secondary values
969  setConstraintSecondaryValues(initial_solution, false);
970 
972  setConstraintSecondaryValues(initial_solution, true);
973 }
974 
975 void
976 NonlinearSystemBase::setPredictor(std::shared_ptr<Predictor> predictor)
977 {
978  _predictor = predictor;
979 }
980 
981 void
983 {
985 
986  _kernels.subdomainSetup(subdomain, tid);
987  _nodal_kernels.subdomainSetup(subdomain, tid);
988  _element_dampers.subdomainSetup(subdomain, tid);
989  _nodal_dampers.subdomainSetup(subdomain, tid);
990 }
991 
994 {
995  if (!_Re_time)
996  {
998 
999  // Most applications don't need the expense of ghosting
1001  _Re_time = &addVector(_Re_time_tag, false, ptype);
1002  }
1003  else if (_need_residual_ghosted && _Re_time->type() == PARALLEL)
1004  {
1005  const auto vector_name = _subproblem.vectorTagName(_Re_time_tag);
1006 
1007  // If an application changes its mind, the libMesh API lets us
1008  // change the vector.
1009  _Re_time = &system().add_vector(vector_name, false, GHOSTED);
1010  }
1011 
1012  return *_Re_time;
1013 }
1014 
1017 {
1018  if (!_Re_non_time)
1019  {
1021 
1022  // Most applications don't need the expense of ghosting
1024  _Re_non_time = &addVector(_Re_non_time_tag, false, ptype);
1025  }
1027  {
1028  const auto vector_name = _subproblem.vectorTagName(_Re_non_time_tag);
1029 
1030  // If an application changes its mind, the libMesh API lets us
1031  // change the vector.
1032  _Re_non_time = &system().add_vector(vector_name, false, GHOSTED);
1033  }
1034 
1035  return *_Re_non_time;
1036 }
1037 
1040 {
1041  mooseDeprecated("Please use getVector()");
1042  switch (tag)
1043  {
1044  case 0:
1045  return getResidualNonTimeVector();
1046 
1047  case 1:
1048  return getResidualTimeVector();
1049 
1050  default:
1051  mooseError("The required residual vector is not available");
1052  }
1053 }
1054 
1055 void
1057 {
1058  THREAD_ID tid = 0; // constraints are going to be done single-threaded
1059  residual.close();
1061  {
1062  const auto & ncs = _constraints.getActiveNodalConstraints();
1063  for (const auto & nc : ncs)
1064  {
1065  std::vector<dof_id_type> & secondary_node_ids = nc->getSecondaryNodeId();
1066  std::vector<dof_id_type> & primary_node_ids = nc->getPrimaryNodeId();
1067 
1068  if ((secondary_node_ids.size() > 0) && (primary_node_ids.size() > 0))
1069  {
1070  _fe_problem.reinitNodes(primary_node_ids, tid);
1071  _fe_problem.reinitNodesNeighbor(secondary_node_ids, tid);
1072  nc->computeResidual(residual);
1073  }
1074  }
1075  _fe_problem.addCachedResidualDirectly(residual, tid);
1076  residual.close();
1077  }
1078 }
1079 
1080 void
1082 {
1083  if (!hasMatrix(systemMatrixTag()))
1084  mooseError(" A system matrix is required");
1085 
1086  auto & jacobian = getMatrix(systemMatrixTag());
1087  THREAD_ID tid = 0; // constraints are going to be done single-threaded
1088 
1090  {
1091  const auto & ncs = _constraints.getActiveNodalConstraints();
1092  for (const auto & nc : ncs)
1093  {
1094  std::vector<dof_id_type> & secondary_node_ids = nc->getSecondaryNodeId();
1095  std::vector<dof_id_type> & primary_node_ids = nc->getPrimaryNodeId();
1096 
1097  if ((secondary_node_ids.size() > 0) && (primary_node_ids.size() > 0))
1098  {
1099  _fe_problem.reinitNodes(primary_node_ids, tid);
1100  _fe_problem.reinitNodesNeighbor(secondary_node_ids, tid);
1101  nc->computeJacobian(jacobian);
1102  }
1103  }
1105  }
1106 }
1107 
1108 void
1110  const BoundaryID secondary_boundary,
1111  const PenetrationInfo & info,
1112  const bool displaced)
1113 {
1114  auto & subproblem = displaced ? static_cast<SubProblem &>(*_fe_problem.getDisplacedProblem())
1115  : static_cast<SubProblem &>(_fe_problem);
1116 
1117  const Elem * primary_elem = info._elem;
1118  unsigned int primary_side = info._side_num;
1119  std::vector<Point> points;
1120  points.push_back(info._closest_point);
1121 
1122  // *These next steps MUST be done in this order!*
1123  // ADL: This is a Chesterton's fence situation. I don't know which calls exactly the above comment
1124  // is referring to. If I had to guess I would guess just the reinitNodeFace and prepareAssembly
1125  // calls since the former will size the variable's dof indices and then the latter will resize the
1126  // residual/Jacobian based off the variable's cached dof indices size
1127 
1128  // This reinits the variables that exist on the secondary node
1129  _fe_problem.reinitNodeFace(&secondary_node, secondary_boundary, 0);
1130 
1131  // This will set aside residual and jacobian space for the variables that have dofs on
1132  // the secondary node
1134 
1135  _fe_problem.setNeighborSubdomainID(primary_elem, 0);
1136 
1137  //
1138  // Reinit material on undisplaced mesh
1139  //
1140 
1141  const Elem * const undisplaced_primary_elem =
1142  displaced ? _mesh.elemPtr(primary_elem->id()) : primary_elem;
1143  const Point undisplaced_primary_physical_point =
1144  [&points, displaced, primary_elem, undisplaced_primary_elem]()
1145  {
1146  if (displaced)
1147  {
1148  const Point reference_point =
1149  FEMap::inverse_map(primary_elem->dim(), primary_elem, points[0]);
1150  return FEMap::map(primary_elem->dim(), undisplaced_primary_elem, reference_point);
1151  }
1152  else
1153  // If our penetration locator is on the reference mesh, then our undisplaced
1154  // physical point is simply the point coming from the penetration locator
1155  return points[0];
1156  }();
1157 
1159  undisplaced_primary_elem, primary_side, {undisplaced_primary_physical_point}, 0);
1160  // Stateful material properties are only initialized for neighbor material data for internal faces
1161  // for discontinuous Galerkin methods or for conforming interfaces for interface kernels. We don't
1162  // have either of those use cases here where we likely have disconnected meshes
1163  _fe_problem.reinitMaterialsNeighbor(primary_elem->subdomain_id(), 0, /*swap_stateful=*/false);
1164 
1165  // Reinit points for constraint enforcement
1166  if (displaced)
1167  subproblem.reinitNeighborPhys(primary_elem, primary_side, points, 0);
1168 }
1169 
1170 void
1172 {
1173 
1174  if (displaced)
1175  mooseAssert(_fe_problem.getDisplacedProblem(),
1176  "If we're calling this method with displaced = true, then we better well have a "
1177  "displaced problem");
1178  auto & subproblem = displaced ? static_cast<SubProblem &>(*_fe_problem.getDisplacedProblem())
1179  : static_cast<SubProblem &>(_fe_problem);
1180  const auto & penetration_locators = subproblem.geomSearchData()._penetration_locators;
1181 
1182  bool constraints_applied = false;
1183 
1184  for (const auto & it : penetration_locators)
1185  {
1186  PenetrationLocator & pen_loc = *(it.second);
1187 
1188  std::vector<dof_id_type> & secondary_nodes = pen_loc._nearest_node._secondary_nodes;
1189 
1190  BoundaryID secondary_boundary = pen_loc._secondary_boundary;
1191  BoundaryID primary_boundary = pen_loc._primary_boundary;
1192 
1193  if (_constraints.hasActiveNodeFaceConstraints(secondary_boundary, displaced))
1194  {
1195  const auto & constraints =
1196  _constraints.getActiveNodeFaceConstraints(secondary_boundary, displaced);
1197  std::unordered_set<unsigned int> needed_mat_props;
1198  for (const auto & constraint : constraints)
1199  {
1200  const auto & mp_deps = constraint->getMatPropDependencies();
1201  needed_mat_props.insert(mp_deps.begin(), mp_deps.end());
1202  }
1203  _fe_problem.setActiveMaterialProperties(needed_mat_props, /*tid=*/0);
1204 
1205  for (unsigned int i = 0; i < secondary_nodes.size(); i++)
1206  {
1207  dof_id_type secondary_node_num = secondary_nodes[i];
1208  Node & secondary_node = _mesh.nodeRef(secondary_node_num);
1209 
1210  if (secondary_node.processor_id() == processor_id())
1211  {
1212  if (pen_loc._penetration_info[secondary_node_num])
1213  {
1214  PenetrationInfo & info = *pen_loc._penetration_info[secondary_node_num];
1215 
1216  reinitNodeFace(secondary_node, secondary_boundary, info, displaced);
1217 
1218  for (const auto & nfc : constraints)
1219  {
1220  if (nfc->isExplicitConstraint())
1221  continue;
1222  // Return if this constraint does not correspond to the primary-secondary pair
1223  // prepared by the outer loops.
1224  // This continue statement is required when, e.g. one secondary surface constrains
1225  // more than one primary surface.
1226  if (nfc->secondaryBoundary() != secondary_boundary ||
1227  nfc->primaryBoundary() != primary_boundary)
1228  continue;
1229 
1230  if (nfc->shouldApply())
1231  {
1232  constraints_applied = true;
1233  nfc->computeSecondaryValue(solution);
1234  }
1235 
1236  if (nfc->hasWritableCoupledVariables())
1237  {
1238  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
1239  for (auto * var : nfc->getWritableCoupledVariables())
1240  {
1241  if (var->isNodalDefined())
1242  var->insert(_fe_problem.getAuxiliarySystem().solution());
1243  }
1244  }
1245  }
1246  }
1247  }
1248  }
1249  }
1250  }
1251 
1252  // go over NodeELemConstraints
1253  std::set<dof_id_type> unique_secondary_node_ids;
1254 
1255  for (const auto & secondary_id : _mesh.meshSubdomains())
1256  {
1257  for (const auto & primary_id : _mesh.meshSubdomains())
1258  {
1259  if (_constraints.hasActiveNodeElemConstraints(secondary_id, primary_id, displaced))
1260  {
1261  const auto & constraints =
1262  _constraints.getActiveNodeElemConstraints(secondary_id, primary_id, displaced);
1263 
1264  // get unique set of ids of all nodes on current block
1265  unique_secondary_node_ids.clear();
1266  const MeshBase & meshhelper = _mesh.getMesh();
1267  for (const auto & elem : as_range(meshhelper.active_subdomain_elements_begin(secondary_id),
1268  meshhelper.active_subdomain_elements_end(secondary_id)))
1269  {
1270  for (auto & n : elem->node_ref_range())
1271  unique_secondary_node_ids.insert(n.id());
1272  }
1273 
1274  for (auto secondary_node_id : unique_secondary_node_ids)
1275  {
1276  Node & secondary_node = _mesh.nodeRef(secondary_node_id);
1277 
1278  // check if secondary node is on current processor
1279  if (secondary_node.processor_id() == processor_id())
1280  {
1281  // This reinits the variables that exist on the secondary node
1282  _fe_problem.reinitNodeFace(&secondary_node, secondary_id, 0);
1283 
1284  // This will set aside residual and jacobian space for the variables that have dofs
1285  // on the secondary node
1287 
1288  for (const auto & nec : constraints)
1289  {
1290  if (nec->shouldApply())
1291  {
1292  constraints_applied = true;
1293  nec->computeSecondaryValue(solution);
1294  }
1295  }
1296  }
1297  }
1298  }
1299  }
1300  }
1301 
1302  // See if constraints were applied anywhere
1303  _communicator.max(constraints_applied);
1304 
1305  if (constraints_applied)
1306  {
1307  solution.close();
1308  update();
1309  }
1310 }
1311 
1312 void
1314 {
1315  // Make sure the residual is in a good state
1316  residual.close();
1317 
1318  if (displaced)
1319  mooseAssert(_fe_problem.getDisplacedProblem(),
1320  "If we're calling this method with displaced = true, then we better well have a "
1321  "displaced problem");
1322  auto & subproblem = displaced ? static_cast<SubProblem &>(*_fe_problem.getDisplacedProblem())
1323  : static_cast<SubProblem &>(_fe_problem);
1324  const auto & penetration_locators = subproblem.geomSearchData()._penetration_locators;
1325 
1326  bool constraints_applied;
1327  bool residual_has_inserted_values = false;
1329  constraints_applied = false;
1330  for (const auto & it : penetration_locators)
1331  {
1333  {
1334  // Reset the constraint_applied flag before each new constraint, as they need to be
1335  // assembled separately
1336  constraints_applied = false;
1337  }
1338  PenetrationLocator & pen_loc = *(it.second);
1339 
1340  std::vector<dof_id_type> & secondary_nodes = pen_loc._nearest_node._secondary_nodes;
1341 
1342  BoundaryID secondary_boundary = pen_loc._secondary_boundary;
1343  BoundaryID primary_boundary = pen_loc._primary_boundary;
1344 
1345  bool has_writable_variables(false);
1346 
1347  if (_constraints.hasActiveNodeFaceConstraints(secondary_boundary, displaced))
1348  {
1349  const auto & constraints =
1350  _constraints.getActiveNodeFaceConstraints(secondary_boundary, displaced);
1351 
1352  for (unsigned int i = 0; i < secondary_nodes.size(); i++)
1353  {
1354  dof_id_type secondary_node_num = secondary_nodes[i];
1355  Node & secondary_node = _mesh.nodeRef(secondary_node_num);
1356 
1357  if (secondary_node.processor_id() == processor_id())
1358  {
1359  if (pen_loc._penetration_info[secondary_node_num])
1360  {
1361  PenetrationInfo & info = *pen_loc._penetration_info[secondary_node_num];
1362 
1363  reinitNodeFace(secondary_node, secondary_boundary, info, displaced);
1364 
1365  for (const auto & nfc : constraints)
1366  {
1367  // Return if this constraint does not correspond to the primary-secondary pair
1368  // prepared by the outer loops.
1369  // This continue statement is required when, e.g. one secondary surface constrains
1370  // more than one primary surface.
1371  if (nfc->secondaryBoundary() != secondary_boundary ||
1372  nfc->primaryBoundary() != primary_boundary)
1373  continue;
1374 
1375  if (nfc->shouldApply())
1376  {
1377  constraints_applied = true;
1378  nfc->computeResidual();
1379 
1380  if (nfc->overwriteSecondaryResidual())
1381  {
1382  // The below will actually overwrite the residual for every single dof that
1383  // lives on the node. We definitely don't want to do that!
1384  // _fe_problem.setResidual(residual, 0);
1385 
1386  const auto & secondary_var = nfc->variable();
1387  const auto & secondary_dofs = secondary_var.dofIndices();
1388  mooseAssert(secondary_dofs.size() == secondary_var.count(),
1389  "We are on a node so there should only be one dof per variable (for "
1390  "an ArrayVariable we should have a number of dofs equal to the "
1391  "number of components");
1392 
1393  // Assume that if the user is overwriting the secondary residual, then they are
1394  // supplying residuals that do not correspond to their other physics
1395  // (e.g. Kernels), hence we should not apply a scalingFactor that is normally
1396  // based on the order of their other physics (e.g. Kernels)
1397  std::vector<Number> values = {nfc->secondaryResidual()};
1398  residual.insert(values, secondary_dofs);
1399  residual_has_inserted_values = true;
1400  }
1401  else
1404  }
1405  if (nfc->hasWritableCoupledVariables())
1406  {
1407  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
1408  has_writable_variables = true;
1409  for (auto * var : nfc->getWritableCoupledVariables())
1410  {
1411  if (var->isNodalDefined())
1412  var->insert(_fe_problem.getAuxiliarySystem().solution());
1413  }
1414  }
1415  }
1416  }
1417  }
1418  }
1419  }
1420  _communicator.max(has_writable_variables);
1421 
1422  if (has_writable_variables)
1423  {
1424  // Explicit contact dynamic constraints write to auxiliary variables and update the old
1425  // displacement solution on the constraint boundaries. Close solutions and update system
1426  // accordingly.
1429  solutionOld().close();
1430  }
1431 
1433  {
1434  // Make sure that secondary contribution to primary are assembled, and ghosts have been
1435  // exchanged, as current primaries might become secondaries on next iteration and will need to
1436  // contribute their former secondaries' contributions to the future primaries. See if
1437  // constraints were applied anywhere
1438  _communicator.max(constraints_applied);
1439 
1440  if (constraints_applied)
1441  {
1442  // If any of the above constraints inserted values in the residual, it needs to be
1443  // assembled before adding the cached residuals below.
1444  _communicator.max(residual_has_inserted_values);
1445  if (residual_has_inserted_values)
1446  {
1447  residual.close();
1448  residual_has_inserted_values = false;
1449  }
1451  residual.close();
1452 
1454  *_residual_ghosted = residual;
1455  }
1456  }
1457  }
1459  {
1460  _communicator.max(constraints_applied);
1461 
1462  if (constraints_applied)
1463  {
1464  // If any of the above constraints inserted values in the residual, it needs to be assembled
1465  // before adding the cached residuals below.
1466  _communicator.max(residual_has_inserted_values);
1467  if (residual_has_inserted_values)
1468  residual.close();
1469 
1471  residual.close();
1472 
1474  *_residual_ghosted = residual;
1475  }
1476  }
1477 
1478  // go over element-element constraint interface
1479  THREAD_ID tid = 0;
1480  const auto & element_pair_locators = subproblem.geomSearchData()._element_pair_locators;
1481  for (const auto & it : element_pair_locators)
1482  {
1483  ElementPairLocator & elem_pair_loc = *(it.second);
1484 
1485  if (_constraints.hasActiveElemElemConstraints(it.first, displaced))
1486  {
1487  // ElemElemConstraint objects
1488  const auto & _element_constraints =
1489  _constraints.getActiveElemElemConstraints(it.first, displaced);
1490 
1491  // go over pair elements
1492  const std::list<std::pair<const Elem *, const Elem *>> & elem_pairs =
1493  elem_pair_loc.getElemPairs();
1494  for (const auto & pr : elem_pairs)
1495  {
1496  const Elem * elem1 = pr.first;
1497  const Elem * elem2 = pr.second;
1498 
1499  if (elem1->processor_id() != processor_id())
1500  continue;
1501 
1502  const ElementPairInfo & info = elem_pair_loc.getElemPairInfo(pr);
1503 
1504  // for each element process constraints on the
1505  for (const auto & ec : _element_constraints)
1506  {
1507  _fe_problem.setCurrentSubdomainID(elem1, tid);
1508  subproblem.reinitElemPhys(elem1, info._elem1_constraint_q_point, tid);
1509  _fe_problem.setNeighborSubdomainID(elem2, tid);
1510  subproblem.reinitNeighborPhys(elem2, info._elem2_constraint_q_point, tid);
1511 
1512  ec->prepareShapes(ec->variable().number());
1513  ec->prepareNeighborShapes(ec->variable().number());
1514 
1515  ec->reinit(info);
1516  ec->computeResidual();
1519  }
1521  }
1522  }
1523  }
1524 
1525  // go over NodeElemConstraints
1526  std::set<dof_id_type> unique_secondary_node_ids;
1527 
1528  constraints_applied = false;
1529  residual_has_inserted_values = false;
1530  bool has_writable_variables = false;
1531  for (const auto & secondary_id : _mesh.meshSubdomains())
1532  {
1533  for (const auto & primary_id : _mesh.meshSubdomains())
1534  {
1535  if (_constraints.hasActiveNodeElemConstraints(secondary_id, primary_id, displaced))
1536  {
1537  const auto & constraints =
1538  _constraints.getActiveNodeElemConstraints(secondary_id, primary_id, displaced);
1539 
1540  // get unique set of ids of all nodes on current block
1541  unique_secondary_node_ids.clear();
1542  const MeshBase & meshhelper = _mesh.getMesh();
1543  for (const auto & elem : as_range(meshhelper.active_subdomain_elements_begin(secondary_id),
1544  meshhelper.active_subdomain_elements_end(secondary_id)))
1545  {
1546  for (auto & n : elem->node_ref_range())
1547  unique_secondary_node_ids.insert(n.id());
1548  }
1549 
1550  for (auto secondary_node_id : unique_secondary_node_ids)
1551  {
1552  Node & secondary_node = _mesh.nodeRef(secondary_node_id);
1553  // check if secondary node is on current processor
1554  if (secondary_node.processor_id() == processor_id())
1555  {
1556  // This reinits the variables that exist on the secondary node
1557  _fe_problem.reinitNodeFace(&secondary_node, secondary_id, 0);
1558 
1559  // This will set aside residual and jacobian space for the variables that have dofs
1560  // on the secondary node
1562 
1563  for (const auto & nec : constraints)
1564  {
1565  if (nec->shouldApply())
1566  {
1567  constraints_applied = true;
1568  nec->computeResidual();
1569 
1570  if (nec->overwriteSecondaryResidual())
1571  {
1572  _fe_problem.setResidual(residual, 0);
1573  residual_has_inserted_values = true;
1574  }
1575  else
1578  }
1579  if (nec->hasWritableCoupledVariables())
1580  {
1581  Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
1582  has_writable_variables = true;
1583  for (auto * var : nec->getWritableCoupledVariables())
1584  {
1585  if (var->isNodalDefined())
1586  var->insert(_fe_problem.getAuxiliarySystem().solution());
1587  }
1588  }
1589  }
1591  }
1592  }
1593  }
1594  }
1595  }
1596  _communicator.max(constraints_applied);
1597 
1598  if (constraints_applied)
1599  {
1600  // If any of the above constraints inserted values in the residual, it needs to be assembled
1601  // before adding the cached residuals below.
1602  _communicator.max(residual_has_inserted_values);
1603  if (residual_has_inserted_values)
1604  residual.close();
1605 
1607  residual.close();
1608 
1610  *_residual_ghosted = residual;
1611  }
1612  _communicator.max(has_writable_variables);
1613 
1614  if (has_writable_variables)
1615  {
1616  // Explicit contact dynamic constraints write to auxiliary variables and update the old
1617  // displacement solution on the constraint boundaries. Close solutions and update system
1618  // accordingly.
1621  solutionOld().close();
1622  }
1623 
1624  // We may have additional tagged vectors that also need to be accumulated
1626 }
1627 
1628 void
1630 {
1631  // Overwrite results from integrator in case we have explicit dynamics contact constraints
1633  ? static_cast<SubProblem &>(*_fe_problem.getDisplacedProblem())
1634  : static_cast<SubProblem &>(_fe_problem);
1635  const auto & penetration_locators = subproblem.geomSearchData()._penetration_locators;
1636 
1637  for (const auto & it : penetration_locators)
1638  {
1639  PenetrationLocator & pen_loc = *(it.second);
1640 
1641  const auto & secondary_nodes = pen_loc._nearest_node._secondary_nodes;
1642  const BoundaryID secondary_boundary = pen_loc._secondary_boundary;
1643  const BoundaryID primary_boundary = pen_loc._primary_boundary;
1644 
1645  if (_constraints.hasActiveNodeFaceConstraints(secondary_boundary, true))
1646  {
1647  const auto & constraints =
1648  _constraints.getActiveNodeFaceConstraints(secondary_boundary, true);
1649  for (const auto i : index_range(secondary_nodes))
1650  {
1651  const auto secondary_node_num = secondary_nodes[i];
1652  const Node & secondary_node = _mesh.nodeRef(secondary_node_num);
1653 
1654  if (secondary_node.processor_id() == processor_id())
1655  if (pen_loc._penetration_info[secondary_node_num])
1656  for (const auto & nfc : constraints)
1657  {
1658  if (!nfc->isExplicitConstraint())
1659  continue;
1660 
1661  // Return if this constraint does not correspond to the primary-secondary pair
1662  // prepared by the outer loops.
1663  // This continue statement is required when, e.g. one secondary surface constrains
1664  // more than one primary surface.
1665  if (nfc->secondaryBoundary() != secondary_boundary ||
1666  nfc->primaryBoundary() != primary_boundary)
1667  continue;
1668 
1669  nfc->overwriteBoundaryVariables(soln, secondary_node);
1670  }
1671  }
1672  }
1673  }
1674  soln.close();
1675 }
1676 
1677 void
1679 {
1680  TIME_SECTION("residualSetup", 3);
1681 
1683 
1684  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
1685  {
1686  _kernels.residualSetup(tid);
1689  if (_doing_dg)
1695  }
1700 
1701  // Avoid recursion
1702  if (this == &_fe_problem.currentNonlinearSystem())
1705 }
1706 
1707 void
1709 {
1710  parallel_object_only();
1711 
1712  TIME_SECTION("computeResidualInternal", 3);
1713 
1714  residualSetup();
1715 
1716  const auto vector_tag_data = _fe_problem.getVectorTags(tags);
1717 
1718  // Residual contributions from UOs - for now this is used for ray tracing
1719  // and ray kernels that contribute to the residual (think line sources)
1720  std::vector<UserObject *> uos;
1722  .query()
1723  .condition<AttribSystem>("UserObject")
1724  .condition<AttribExecOns>(EXEC_PRE_KERNELS)
1725  .queryInto(uos);
1726  for (auto & uo : uos)
1727  uo->residualSetup();
1728  for (auto & uo : uos)
1729  {
1730  uo->initialize();
1731  uo->execute();
1732  uo->finalize();
1733  }
1734 
1735  // reinit scalar variables
1736  for (unsigned int tid = 0; tid < libMesh::n_threads(); tid++)
1738 
1739  // residual contributions from the domain
1740  PARALLEL_TRY
1741  {
1742  TIME_SECTION("Kernels", 3 /*, "Computing Kernels"*/);
1743 
1745 
1747  Threads::parallel_reduce(elem_range, cr);
1748 
1749  // We pass face information directly to FV residual objects for their evaluation. Consequently
1750  // we must make sure to do separate threaded loops for 1) undisplaced face information objects
1751  // and undisplaced residual objects and 2) displaced face information objects and displaced
1752  // residual objects
1754  if (_fe_problem.haveFV())
1755  {
1757  _fe_problem, this->number(), tags, /*on_displaced=*/false);
1759  Threads::parallel_reduce(faces, fvr);
1760  }
1762  displaced_problem && displaced_problem->haveFV())
1763  {
1765  _fe_problem, this->number(), tags, /*on_displaced=*/true);
1766  FVRange faces(displaced_problem->mesh().ownedFaceInfoBegin(),
1767  displaced_problem->mesh().ownedFaceInfoEnd());
1768  Threads::parallel_reduce(faces, fvr);
1769  }
1770 
1771  unsigned int n_threads = libMesh::n_threads();
1772  for (unsigned int i = 0; i < n_threads;
1773  i++) // Add any cached residuals that might be hanging around
1775  }
1776  PARALLEL_CATCH;
1777 
1778  // residual contributions from the scalar kernels
1779  PARALLEL_TRY
1780  {
1781  // do scalar kernels (not sure how to thread this)
1783  {
1784  TIME_SECTION("ScalarKernels", 3 /*, "Computing ScalarKernels"*/);
1785 
1786  MooseObjectWarehouse<ScalarKernelBase> * scalar_kernel_warehouse;
1787  // This code should be refactored once we can do tags for scalar
1788  // kernels
1789  // Should redo this based on Warehouse
1790  if (!tags.size() || tags.size() == _fe_problem.numVectorTags(Moose::VECTOR_TAG_RESIDUAL))
1791  scalar_kernel_warehouse = &_scalar_kernels;
1792  else if (tags.size() == 1)
1793  scalar_kernel_warehouse =
1794  &(_scalar_kernels.getVectorTagObjectWarehouse(*(tags.begin()), 0));
1795  else
1796  // scalar_kernels is not threading
1797  scalar_kernel_warehouse = &(_scalar_kernels.getVectorTagsObjectWarehouse(tags, 0));
1798 
1799  bool have_scalar_contributions = false;
1800  const auto & scalars = scalar_kernel_warehouse->getActiveObjects();
1801  for (const auto & scalar_kernel : scalars)
1802  {
1803  scalar_kernel->reinit();
1804  const std::vector<dof_id_type> & dof_indices = scalar_kernel->variable().dofIndices();
1805  const DofMap & dof_map = scalar_kernel->variable().dofMap();
1806  const dof_id_type first_dof = dof_map.first_dof();
1807  const dof_id_type end_dof = dof_map.end_dof();
1808  for (dof_id_type dof : dof_indices)
1809  {
1810  if (dof >= first_dof && dof < end_dof)
1811  {
1812  scalar_kernel->computeResidual();
1813  have_scalar_contributions = true;
1814  break;
1815  }
1816  }
1817  }
1818  if (have_scalar_contributions)
1820  }
1821  }
1822  PARALLEL_CATCH;
1823 
1824  // residual contributions from Block NodalKernels
1825  PARALLEL_TRY
1826  {
1828  {
1829  TIME_SECTION("NodalKernels", 3 /*, "Computing NodalKernels"*/);
1830 
1832 
1834 
1835  if (range.begin() != range.end())
1836  {
1837  _fe_problem.reinitNode(*range.begin(), 0);
1838 
1839  Threads::parallel_reduce(range, cnk);
1840 
1841  unsigned int n_threads = libMesh::n_threads();
1842  for (unsigned int i = 0; i < n_threads;
1843  i++) // Add any cached residuals that might be hanging around
1845  }
1846  }
1847  }
1848  PARALLEL_CATCH;
1849 
1851  // We computed the volumetric objects. We can return now before we get into
1852  // any strongly enforced constraint conditions or penalty-type objects
1853  // (DGKernels, IntegratedBCs, InterfaceKernels, Constraints)
1854  return;
1855 
1856  // residual contributions from boundary NodalKernels
1857  PARALLEL_TRY
1858  {
1860  {
1861  TIME_SECTION("NodalKernelBCs", 3 /*, "Computing NodalKernelBCs"*/);
1862 
1864 
1866 
1867  Threads::parallel_reduce(bnd_node_range, cnk);
1868 
1869  unsigned int n_threads = libMesh::n_threads();
1870  for (unsigned int i = 0; i < n_threads;
1871  i++) // Add any cached residuals that might be hanging around
1873  }
1874  }
1875  PARALLEL_CATCH;
1876 
1878 
1879  if (_residual_copy.get())
1880  {
1881  _Re_non_time->close();
1883  }
1884 
1886  {
1887  _Re_non_time->close();
1890  }
1891 
1892  PARALLEL_TRY { computeDiracContributions(tags, false); }
1893  PARALLEL_CATCH;
1894 
1896  {
1897  PARALLEL_TRY { enforceNodalConstraintsResidual(*_Re_non_time); }
1898  PARALLEL_CATCH;
1899  _Re_non_time->close();
1900  }
1901 
1902  // Add in Residual contributions from other Constraints
1904  {
1905  PARALLEL_TRY
1906  {
1907  // Undisplaced Constraints
1909 
1910  // Displaced Constraints
1913 
1916  }
1917  PARALLEL_CATCH;
1918  _Re_non_time->close();
1919  }
1920 
1921  // Accumulate the occurrence of solution invalid warnings for the current iteration cumulative
1922  // counters
1925 }
1926 
1927 void
1929  const std::set<TagID> & matrix_tags)
1930 {
1931  TIME_SECTION("computeResidualAndJacobianInternal", 3);
1932 
1933  // Make matrix ready to use
1935 
1936  for (auto tag : matrix_tags)
1937  {
1938  if (!hasMatrix(tag))
1939  continue;
1940 
1941  auto & jacobian = getMatrix(tag);
1942  // Necessary for speed
1943  if (auto petsc_matrix = dynamic_cast<PetscMatrix<Number> *>(&jacobian))
1944  {
1945  LibmeshPetscCall(MatSetOption(petsc_matrix->mat(),
1946  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
1947  PETSC_TRUE));
1949  LibmeshPetscCall(
1950  MatSetOption(petsc_matrix->mat(), MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
1952  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
1953  MAT_IGNORE_ZERO_ENTRIES,
1954  PETSC_TRUE));
1955  }
1956  }
1957 
1958  residualSetup();
1959 
1960  // Residual contributions from UOs - for now this is used for ray tracing
1961  // and ray kernels that contribute to the residual (think line sources)
1962  std::vector<UserObject *> uos;
1964  .query()
1965  .condition<AttribSystem>("UserObject")
1966  .condition<AttribExecOns>(EXEC_PRE_KERNELS)
1967  .queryInto(uos);
1968  for (auto & uo : uos)
1969  uo->residualSetup();
1970  for (auto & uo : uos)
1971  {
1972  uo->initialize();
1973  uo->execute();
1974  uo->finalize();
1975  }
1976 
1977  // reinit scalar variables
1978  for (unsigned int tid = 0; tid < libMesh::n_threads(); tid++)
1980 
1981  // residual contributions from the domain
1982  PARALLEL_TRY
1983  {
1984  TIME_SECTION("Kernels", 3 /*, "Computing Kernels"*/);
1985 
1987 
1988  ComputeResidualAndJacobianThread crj(_fe_problem, vector_tags, matrix_tags);
1989  Threads::parallel_reduce(elem_range, crj);
1990 
1992  if (_fe_problem.haveFV())
1993  {
1995  _fe_problem, this->number(), vector_tags, matrix_tags, /*on_displaced=*/false);
1997  Threads::parallel_reduce(faces, fvrj);
1998  }
2000  displaced_problem && displaced_problem->haveFV())
2001  {
2003  _fe_problem, this->number(), vector_tags, matrix_tags, /*on_displaced=*/true);
2004  FVRange faces(displaced_problem->mesh().ownedFaceInfoBegin(),
2005  displaced_problem->mesh().ownedFaceInfoEnd());
2006  Threads::parallel_reduce(faces, fvr);
2007  }
2008 
2010 
2011  unsigned int n_threads = libMesh::n_threads();
2012  for (unsigned int i = 0; i < n_threads;
2013  i++) // Add any cached residuals that might be hanging around
2014  {
2017  }
2018  }
2019  PARALLEL_CATCH;
2020 }
2021 
2022 void
2024 {
2025  _nl_vector_tags.clear();
2026 
2027  const auto & residual_vector_tags = _fe_problem.getVectorTags(Moose::VECTOR_TAG_RESIDUAL);
2028  for (const auto & residual_vector_tag : residual_vector_tags)
2029  _nl_vector_tags.insert(residual_vector_tag._id);
2030 
2032  computeNodalBCs(residual, _nl_vector_tags);
2034 }
2035 
2036 void
2037 NonlinearSystemBase::computeNodalBCs(NumericVector<Number> & residual, const std::set<TagID> & tags)
2038 {
2040 
2041  computeNodalBCs(tags);
2042 
2044 }
2045 
2046 void
2047 NonlinearSystemBase::computeNodalBCs(const std::set<TagID> & tags)
2048 {
2049  // We need to close the diag_save_in variables on the aux system before NodalBCBases clear the
2050  // dofs on boundary nodes
2051  if (_has_save_in)
2053 
2054  // Select nodal kernels
2055  MooseObjectWarehouse<NodalBCBase> * nbc_warehouse;
2056 
2057  if (tags.size() == _fe_problem.numVectorTags(Moose::VECTOR_TAG_RESIDUAL) || !tags.size())
2058  nbc_warehouse = &_nodal_bcs;
2059  else if (tags.size() == 1)
2060  nbc_warehouse = &(_nodal_bcs.getVectorTagObjectWarehouse(*(tags.begin()), 0));
2061  else
2062  nbc_warehouse = &(_nodal_bcs.getVectorTagsObjectWarehouse(tags, 0));
2063 
2064  // Return early if there is no nodal kernel
2065  if (!nbc_warehouse->size())
2066  return;
2067 
2068  PARALLEL_TRY
2069  {
2071 
2072  if (!bnd_nodes.empty())
2073  {
2074  TIME_SECTION("NodalBCs", 3 /*, "Computing NodalBCs"*/);
2075 
2076  for (const auto & bnode : bnd_nodes)
2077  {
2078  BoundaryID boundary_id = bnode->_bnd_id;
2079  Node * node = bnode->_node;
2080 
2081  if (node->processor_id() == processor_id() &&
2082  nbc_warehouse->hasActiveBoundaryObjects(boundary_id))
2083  {
2084  // reinit variables in nodes
2085  _fe_problem.reinitNodeFace(node, boundary_id, 0);
2086 
2087  const auto & bcs = nbc_warehouse->getActiveBoundaryObjects(boundary_id);
2088  for (const auto & nbc : bcs)
2089  if (nbc->shouldApply())
2090  nbc->computeResidual();
2091  }
2092  }
2093  }
2094  }
2095  PARALLEL_CATCH;
2096 
2097  if (_Re_time)
2098  _Re_time->close();
2099  _Re_non_time->close();
2100 }
2101 
2102 void
2104 {
2105  PARALLEL_TRY
2106  {
2108 
2109  if (!bnd_nodes.empty())
2110  {
2111  TIME_SECTION("NodalBCs", 3 /*, "Computing NodalBCs"*/);
2112 
2113  for (const auto & bnode : bnd_nodes)
2114  {
2115  BoundaryID boundary_id = bnode->_bnd_id;
2116  Node * node = bnode->_node;
2117 
2118  if (node->processor_id() == processor_id())
2119  {
2120  // reinit variables in nodes
2121  _fe_problem.reinitNodeFace(node, boundary_id, 0);
2122  if (_nodal_bcs.hasActiveBoundaryObjects(boundary_id))
2123  {
2124  const auto & bcs = _nodal_bcs.getActiveBoundaryObjects(boundary_id);
2125  for (const auto & nbc : bcs)
2126  if (nbc->shouldApply())
2127  nbc->computeResidualAndJacobian();
2128  }
2129  }
2130  }
2131  }
2132  }
2133  PARALLEL_CATCH;
2134 
2135  // Set the cached NodalBCBase values in the Jacobian matrix
2137 }
2138 
2139 void
2140 NonlinearSystemBase::getNodeDofs(dof_id_type node_id, std::vector<dof_id_type> & dofs)
2141 {
2142  const Node & node = _mesh.nodeRef(node_id);
2143  unsigned int s = number();
2144  if (node.has_dofs(s))
2145  {
2146  for (unsigned int v = 0; v < nVariables(); v++)
2147  for (unsigned int c = 0; c < node.n_comp(s, v); c++)
2148  dofs.push_back(node.dof_number(s, v, c));
2149  }
2150 }
2151 
2152 void
2154  GeometricSearchData & geom_search_data,
2155  std::unordered_map<dof_id_type, std::vector<dof_id_type>> & graph)
2156 {
2157  const auto & node_to_elem_map = _mesh.nodeToElemMap();
2158  const auto & nearest_node_locators = geom_search_data._nearest_node_locators;
2159  for (const auto & it : nearest_node_locators)
2160  {
2161  std::vector<dof_id_type> & secondary_nodes = it.second->_secondary_nodes;
2162 
2163  for (const auto & secondary_node : secondary_nodes)
2164  {
2165  std::set<dof_id_type> unique_secondary_indices;
2166  std::set<dof_id_type> unique_primary_indices;
2167 
2168  auto node_to_elem_pair = node_to_elem_map.find(secondary_node);
2169  if (node_to_elem_pair != node_to_elem_map.end())
2170  {
2171  const std::vector<dof_id_type> & elems = node_to_elem_pair->second;
2172 
2173  // Get the dof indices from each elem connected to the node
2174  for (const auto & cur_elem : elems)
2175  {
2176  std::vector<dof_id_type> dof_indices;
2177  dofMap().dof_indices(_mesh.elemPtr(cur_elem), dof_indices);
2178 
2179  for (const auto & dof : dof_indices)
2180  unique_secondary_indices.insert(dof);
2181  }
2182  }
2183 
2184  std::vector<dof_id_type> primary_nodes = it.second->_neighbor_nodes[secondary_node];
2185 
2186  for (const auto & primary_node : primary_nodes)
2187  {
2188  auto primary_node_to_elem_pair = node_to_elem_map.find(primary_node);
2189  mooseAssert(primary_node_to_elem_pair != node_to_elem_map.end(),
2190  "Missing entry in node to elem map");
2191  const std::vector<dof_id_type> & primary_node_elems = primary_node_to_elem_pair->second;
2192 
2193  // Get the dof indices from each elem connected to the node
2194  for (const auto & cur_elem : primary_node_elems)
2195  {
2196  std::vector<dof_id_type> dof_indices;
2197  dofMap().dof_indices(_mesh.elemPtr(cur_elem), dof_indices);
2198 
2199  for (const auto & dof : dof_indices)
2200  unique_primary_indices.insert(dof);
2201  }
2202  }
2203 
2204  for (const auto & secondary_id : unique_secondary_indices)
2205  for (const auto & primary_id : unique_primary_indices)
2206  {
2207  graph[secondary_id].push_back(primary_id);
2208  graph[primary_id].push_back(secondary_id);
2209  }
2210  }
2211  }
2212 
2213  // handle node-to-node constraints
2214  const auto & ncs = _constraints.getActiveNodalConstraints();
2215  for (const auto & nc : ncs)
2216  {
2217  std::vector<dof_id_type> primary_dofs;
2218  std::vector<dof_id_type> & primary_node_ids = nc->getPrimaryNodeId();
2219  for (const auto & node_id : primary_node_ids)
2220  {
2221  Node * node = _mesh.queryNodePtr(node_id);
2222  if (node && node->processor_id() == this->processor_id())
2223  {
2224  getNodeDofs(node_id, primary_dofs);
2225  }
2226  }
2227 
2228  _communicator.allgather(primary_dofs);
2229 
2230  std::vector<dof_id_type> secondary_dofs;
2231  std::vector<dof_id_type> & secondary_node_ids = nc->getSecondaryNodeId();
2232  for (const auto & node_id : secondary_node_ids)
2233  {
2234  Node * node = _mesh.queryNodePtr(node_id);
2235  if (node && node->processor_id() == this->processor_id())
2236  {
2237  getNodeDofs(node_id, secondary_dofs);
2238  }
2239  }
2240 
2241  _communicator.allgather(secondary_dofs);
2242 
2243  for (const auto & primary_id : primary_dofs)
2244  for (const auto & secondary_id : secondary_dofs)
2245  {
2246  graph[primary_id].push_back(secondary_id);
2247  graph[secondary_id].push_back(primary_id);
2248  }
2249  }
2250 
2251  // Make every entry sorted and unique
2252  for (auto & it : graph)
2253  {
2254  std::vector<dof_id_type> & row = it.second;
2255  std::sort(row.begin(), row.end());
2256  std::vector<dof_id_type>::iterator uit = std::unique(row.begin(), row.end());
2257  row.resize(uit - row.begin());
2258  }
2259 }
2260 
2261 void
2263 {
2264  if (!hasMatrix(systemMatrixTag()))
2265  mooseError("Need a system matrix ");
2266 
2267  // At this point, have no idea how to make
2268  // this work with tag system
2269  auto & jacobian = getMatrix(systemMatrixTag());
2270 
2271  std::unordered_map<dof_id_type, std::vector<dof_id_type>> graph;
2272 
2273  findImplicitGeometricCouplingEntries(geom_search_data, graph);
2274 
2275  for (const auto & it : graph)
2276  {
2277  dof_id_type dof = it.first;
2278  const auto & row = it.second;
2279 
2280  for (const auto & coupled_dof : row)
2281  jacobian.add(dof, coupled_dof, 0);
2282  }
2283 }
2284 
2285 void
2287  bool displaced)
2288 {
2289  if (!hasMatrix(systemMatrixTag()))
2290  mooseError("A system matrix is required");
2291 
2292  auto & jacobian = getMatrix(systemMatrixTag());
2293 
2295  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
2296  MAT_NEW_NONZERO_ALLOCATION_ERR,
2297  PETSC_FALSE));
2299  LibmeshPetscCall(MatSetOption(
2300  static_cast<PetscMatrix<Number> &>(jacobian).mat(), MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE));
2301 
2302  std::vector<numeric_index_type> zero_rows;
2303 
2304  if (displaced)
2305  mooseAssert(_fe_problem.getDisplacedProblem(),
2306  "If we're calling this method with displaced = true, then we better well have a "
2307  "displaced problem");
2308  auto & subproblem = displaced ? static_cast<SubProblem &>(*_fe_problem.getDisplacedProblem())
2309  : static_cast<SubProblem &>(_fe_problem);
2310  const auto & penetration_locators = subproblem.geomSearchData()._penetration_locators;
2311 
2312  bool constraints_applied;
2314  constraints_applied = false;
2315  for (const auto & it : penetration_locators)
2316  {
2318  {
2319  // Reset the constraint_applied flag before each new constraint, as they need to be
2320  // assembled separately
2321  constraints_applied = false;
2322  }
2323  PenetrationLocator & pen_loc = *(it.second);
2324 
2325  std::vector<dof_id_type> & secondary_nodes = pen_loc._nearest_node._secondary_nodes;
2326 
2327  BoundaryID secondary_boundary = pen_loc._secondary_boundary;
2328  BoundaryID primary_boundary = pen_loc._primary_boundary;
2329 
2330  zero_rows.clear();
2331  if (_constraints.hasActiveNodeFaceConstraints(secondary_boundary, displaced))
2332  {
2333  const auto & constraints =
2334  _constraints.getActiveNodeFaceConstraints(secondary_boundary, displaced);
2335 
2336  for (const auto & secondary_node_num : secondary_nodes)
2337  {
2338  Node & secondary_node = _mesh.nodeRef(secondary_node_num);
2339 
2340  if (secondary_node.processor_id() == processor_id())
2341  {
2342  if (pen_loc._penetration_info[secondary_node_num])
2343  {
2344  PenetrationInfo & info = *pen_loc._penetration_info[secondary_node_num];
2345 
2346  reinitNodeFace(secondary_node, secondary_boundary, info, displaced);
2348 
2349  for (const auto & nfc : constraints)
2350  {
2351  if (nfc->isExplicitConstraint())
2352  continue;
2353  // Return if this constraint does not correspond to the primary-secondary pair
2354  // prepared by the outer loops.
2355  // This continue statement is required when, e.g. one secondary surface constrains
2356  // more than one primary surface.
2357  if (nfc->secondaryBoundary() != secondary_boundary ||
2358  nfc->primaryBoundary() != primary_boundary)
2359  continue;
2360 
2361  nfc->_jacobian = &jacobian_to_view;
2362 
2363  if (nfc->shouldApply())
2364  {
2365  constraints_applied = true;
2366 
2367  nfc->prepareShapes(nfc->variable().number());
2368  nfc->prepareNeighborShapes(nfc->variable().number());
2369 
2370  nfc->computeJacobian();
2371 
2372  if (nfc->overwriteSecondaryJacobian())
2373  {
2374  // Add this variable's dof's row to be zeroed
2375  zero_rows.push_back(nfc->variable().nodalDofIndex());
2376  }
2377 
2378  std::vector<dof_id_type> secondary_dofs(1, nfc->variable().nodalDofIndex());
2379 
2380  // Assume that if the user is overwriting the secondary Jacobian, then they are
2381  // supplying Jacobians that do not correspond to their other physics
2382  // (e.g. Kernels), hence we should not apply a scalingFactor that is normally
2383  // based on the order of their other physics (e.g. Kernels)
2384  Real scaling_factor =
2385  nfc->overwriteSecondaryJacobian() ? 1. : nfc->variable().scalingFactor();
2386 
2387  // Cache the jacobian block for the secondary side
2388  nfc->addJacobian(_fe_problem.assembly(0, number()),
2389  nfc->_Kee,
2390  secondary_dofs,
2391  nfc->_connected_dof_indices,
2392  scaling_factor);
2393 
2394  // Cache Ken, Kne, Knn
2395  if (nfc->addCouplingEntriesToJacobian())
2396  {
2397  // Make sure we use a proper scaling factor (e.g. don't use an interior scaling
2398  // factor when we're overwriting secondary stuff)
2399  nfc->addJacobian(_fe_problem.assembly(0, number()),
2400  nfc->_Ken,
2401  secondary_dofs,
2402  nfc->primaryVariable().dofIndicesNeighbor(),
2403  scaling_factor);
2404 
2405  // Use _connected_dof_indices to get all the correct columns
2406  nfc->addJacobian(_fe_problem.assembly(0, number()),
2407  nfc->_Kne,
2408  nfc->primaryVariable().dofIndicesNeighbor(),
2409  nfc->_connected_dof_indices,
2410  nfc->primaryVariable().scalingFactor());
2411 
2412  // We've handled Ken and Kne, finally handle Knn
2414  }
2415 
2416  // Do the off-diagonals next
2417  const std::vector<MooseVariableFEBase *> coupled_vars = nfc->getCoupledMooseVars();
2418  for (const auto & jvar : coupled_vars)
2419  {
2420  // Only compute jacobians for nonlinear variables
2421  if (jvar->kind() != Moose::VAR_SOLVER)
2422  continue;
2423 
2424  // Only compute Jacobian entries if this coupling is being used by the
2425  // preconditioner
2426  if (nfc->variable().number() == jvar->number() ||
2428  nfc->variable().number(), jvar->number(), this->number()))
2429  continue;
2430 
2431  // Need to zero out the matrices first
2433 
2434  nfc->prepareShapes(nfc->variable().number());
2435  nfc->prepareNeighborShapes(jvar->number());
2436 
2437  nfc->computeOffDiagJacobian(jvar->number());
2438 
2439  // Cache the jacobian block for the secondary side
2440  nfc->addJacobian(_fe_problem.assembly(0, number()),
2441  nfc->_Kee,
2442  secondary_dofs,
2443  nfc->_connected_dof_indices,
2444  scaling_factor);
2445 
2446  // Cache Ken, Kne, Knn
2447  if (nfc->addCouplingEntriesToJacobian())
2448  {
2449  // Make sure we use a proper scaling factor (e.g. don't use an interior scaling
2450  // factor when we're overwriting secondary stuff)
2451  nfc->addJacobian(_fe_problem.assembly(0, number()),
2452  nfc->_Ken,
2453  secondary_dofs,
2454  jvar->dofIndicesNeighbor(),
2455  scaling_factor);
2456 
2457  // Use _connected_dof_indices to get all the correct columns
2458  nfc->addJacobian(_fe_problem.assembly(0, number()),
2459  nfc->_Kne,
2460  nfc->variable().dofIndicesNeighbor(),
2461  nfc->_connected_dof_indices,
2462  nfc->variable().scalingFactor());
2463 
2464  // We've handled Ken and Kne, finally handle Knn
2466  }
2467  }
2468  }
2469  }
2470  }
2471  }
2472  }
2473  }
2475  {
2476  // See if constraints were applied anywhere
2477  _communicator.max(constraints_applied);
2478 
2479  if (constraints_applied)
2480  {
2481  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
2482  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
2483  PETSC_TRUE));
2484 
2485  jacobian.close();
2486  jacobian.zero_rows(zero_rows, 0.0);
2487  jacobian.close();
2489  jacobian.close();
2490  }
2491  }
2492  }
2494  {
2495  // See if constraints were applied anywhere
2496  _communicator.max(constraints_applied);
2497 
2498  if (constraints_applied)
2499  {
2500  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
2501  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
2502  PETSC_TRUE));
2503 
2504  jacobian.close();
2505  jacobian.zero_rows(zero_rows, 0.0);
2506  jacobian.close();
2508  jacobian.close();
2509  }
2510  }
2511 
2512  THREAD_ID tid = 0;
2513  // go over element-element constraint interface
2514  const auto & element_pair_locators = subproblem.geomSearchData()._element_pair_locators;
2515  for (const auto & it : element_pair_locators)
2516  {
2517  ElementPairLocator & elem_pair_loc = *(it.second);
2518 
2519  if (_constraints.hasActiveElemElemConstraints(it.first, displaced))
2520  {
2521  // ElemElemConstraint objects
2522  const auto & _element_constraints =
2523  _constraints.getActiveElemElemConstraints(it.first, displaced);
2524 
2525  // go over pair elements
2526  const std::list<std::pair<const Elem *, const Elem *>> & elem_pairs =
2527  elem_pair_loc.getElemPairs();
2528  for (const auto & pr : elem_pairs)
2529  {
2530  const Elem * elem1 = pr.first;
2531  const Elem * elem2 = pr.second;
2532 
2533  if (elem1->processor_id() != processor_id())
2534  continue;
2535 
2536  const ElementPairInfo & info = elem_pair_loc.getElemPairInfo(pr);
2537 
2538  // for each element process constraints on the
2539  for (const auto & ec : _element_constraints)
2540  {
2541  _fe_problem.setCurrentSubdomainID(elem1, tid);
2542  subproblem.reinitElemPhys(elem1, info._elem1_constraint_q_point, tid);
2543  _fe_problem.setNeighborSubdomainID(elem2, tid);
2544  subproblem.reinitNeighborPhys(elem2, info._elem2_constraint_q_point, tid);
2545 
2546  ec->prepareShapes(ec->variable().number());
2547  ec->prepareNeighborShapes(ec->variable().number());
2548 
2549  ec->reinit(info);
2550  ec->computeJacobian();
2553  }
2555  }
2556  }
2557  }
2558 
2559  // go over NodeElemConstraints
2560  std::set<dof_id_type> unique_secondary_node_ids;
2561  constraints_applied = false;
2562  for (const auto & secondary_id : _mesh.meshSubdomains())
2563  {
2564  for (const auto & primary_id : _mesh.meshSubdomains())
2565  {
2566  if (_constraints.hasActiveNodeElemConstraints(secondary_id, primary_id, displaced))
2567  {
2568  const auto & constraints =
2569  _constraints.getActiveNodeElemConstraints(secondary_id, primary_id, displaced);
2570 
2571  // get unique set of ids of all nodes on current block
2572  unique_secondary_node_ids.clear();
2573  const MeshBase & meshhelper = _mesh.getMesh();
2574  for (const auto & elem : as_range(meshhelper.active_subdomain_elements_begin(secondary_id),
2575  meshhelper.active_subdomain_elements_end(secondary_id)))
2576  {
2577  for (auto & n : elem->node_ref_range())
2578  unique_secondary_node_ids.insert(n.id());
2579  }
2580 
2581  for (auto secondary_node_id : unique_secondary_node_ids)
2582  {
2583  const Node & secondary_node = _mesh.nodeRef(secondary_node_id);
2584  // check if secondary node is on current processor
2585  if (secondary_node.processor_id() == processor_id())
2586  {
2587  // This reinits the variables that exist on the secondary node
2588  _fe_problem.reinitNodeFace(&secondary_node, secondary_id, 0);
2589 
2590  // This will set aside residual and jacobian space for the variables that have dofs
2591  // on the secondary node
2594 
2595  for (const auto & nec : constraints)
2596  {
2597  if (nec->shouldApply())
2598  {
2599  constraints_applied = true;
2600 
2601  nec->_jacobian = &jacobian_to_view;
2602  nec->prepareShapes(nec->variable().number());
2603  nec->prepareNeighborShapes(nec->variable().number());
2604 
2605  nec->computeJacobian();
2606 
2607  if (nec->overwriteSecondaryJacobian())
2608  {
2609  // Add this variable's dof's row to be zeroed
2610  zero_rows.push_back(nec->variable().nodalDofIndex());
2611  }
2612 
2613  std::vector<dof_id_type> secondary_dofs(1, nec->variable().nodalDofIndex());
2614 
2615  // Cache the jacobian block for the secondary side
2616  nec->addJacobian(_fe_problem.assembly(0, number()),
2617  nec->_Kee,
2618  secondary_dofs,
2619  nec->_connected_dof_indices,
2620  nec->variable().scalingFactor());
2621 
2622  // Cache the jacobian block for the primary side
2623  nec->addJacobian(_fe_problem.assembly(0, number()),
2624  nec->_Kne,
2625  nec->primaryVariable().dofIndicesNeighbor(),
2626  nec->_connected_dof_indices,
2627  nec->primaryVariable().scalingFactor());
2628 
2631 
2632  // Do the off-diagonals next
2633  const std::vector<MooseVariableFEBase *> coupled_vars = nec->getCoupledMooseVars();
2634  for (const auto & jvar : coupled_vars)
2635  {
2636  // Only compute jacobians for nonlinear variables
2637  if (jvar->kind() != Moose::VAR_SOLVER)
2638  continue;
2639 
2640  // Only compute Jacobian entries if this coupling is being used by the
2641  // preconditioner
2642  if (nec->variable().number() == jvar->number() ||
2644  nec->variable().number(), jvar->number(), this->number()))
2645  continue;
2646 
2647  // Need to zero out the matrices first
2649 
2650  nec->prepareShapes(nec->variable().number());
2651  nec->prepareNeighborShapes(jvar->number());
2652 
2653  nec->computeOffDiagJacobian(jvar->number());
2654 
2655  // Cache the jacobian block for the secondary side
2656  nec->addJacobian(_fe_problem.assembly(0, number()),
2657  nec->_Kee,
2658  secondary_dofs,
2659  nec->_connected_dof_indices,
2660  nec->variable().scalingFactor());
2661 
2662  // Cache the jacobian block for the primary side
2663  nec->addJacobian(_fe_problem.assembly(0, number()),
2664  nec->_Kne,
2665  nec->variable().dofIndicesNeighbor(),
2666  nec->_connected_dof_indices,
2667  nec->variable().scalingFactor());
2668 
2671  }
2672  }
2673  }
2674  }
2675  }
2676  }
2677  }
2678  }
2679  // See if constraints were applied anywhere
2680  _communicator.max(constraints_applied);
2681 
2682  if (constraints_applied)
2683  {
2684  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
2685  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
2686  PETSC_TRUE));
2687 
2688  jacobian.close();
2689  jacobian.zero_rows(zero_rows, 0.0);
2690  jacobian.close();
2692  jacobian.close();
2693  }
2694 }
2695 
2696 void
2698 {
2699  MooseObjectWarehouse<ScalarKernelBase> * scalar_kernel_warehouse;
2700 
2701  if (!tags.size() || tags.size() == _fe_problem.numMatrixTags())
2702  scalar_kernel_warehouse = &_scalar_kernels;
2703  else if (tags.size() == 1)
2704  scalar_kernel_warehouse = &(_scalar_kernels.getMatrixTagObjectWarehouse(*(tags.begin()), 0));
2705  else
2706  scalar_kernel_warehouse = &(_scalar_kernels.getMatrixTagsObjectWarehouse(tags, 0));
2707 
2708  // Compute the diagonal block for scalar variables
2709  if (scalar_kernel_warehouse->hasActiveObjects())
2710  {
2711  const auto & scalars = scalar_kernel_warehouse->getActiveObjects();
2712 
2713  _fe_problem.reinitScalars(/*tid=*/0);
2714 
2715  _fe_problem.reinitOffDiagScalars(/*_tid*/ 0);
2716 
2717  bool have_scalar_contributions = false;
2718  for (const auto & kernel : scalars)
2719  {
2720  if (!kernel->computesJacobian())
2721  continue;
2722 
2723  kernel->reinit();
2724  const std::vector<dof_id_type> & dof_indices = kernel->variable().dofIndices();
2725  const DofMap & dof_map = kernel->variable().dofMap();
2726  const dof_id_type first_dof = dof_map.first_dof();
2727  const dof_id_type end_dof = dof_map.end_dof();
2728  for (dof_id_type dof : dof_indices)
2729  {
2730  if (dof >= first_dof && dof < end_dof)
2731  {
2732  kernel->computeJacobian();
2733  _fe_problem.addJacobianOffDiagScalar(kernel->variable().number());
2734  have_scalar_contributions = true;
2735  break;
2736  }
2737  }
2738  }
2739 
2740  if (have_scalar_contributions)
2742  }
2743 }
2744 
2745 void
2747 {
2749 
2750  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
2751  {
2752  _kernels.jacobianSetup(tid);
2755  if (_doing_dg)
2761  }
2766 
2767  // Avoid recursion
2768  if (this == &_fe_problem.currentNonlinearSystem())
2771 }
2772 
2773 void
2775 {
2776  TIME_SECTION("computeJacobianInternal", 3);
2777 
2779 
2780  // Make matrix ready to use
2782 
2783  for (auto tag : tags)
2784  {
2785  if (!hasMatrix(tag))
2786  continue;
2787 
2788  auto & jacobian = getMatrix(tag);
2789  // Necessary for speed
2790  if (auto petsc_matrix = dynamic_cast<PetscMatrix<Number> *>(&jacobian))
2791  {
2792  LibmeshPetscCall(MatSetOption(petsc_matrix->mat(),
2793  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
2794  PETSC_TRUE));
2796  LibmeshPetscCall(
2797  MatSetOption(petsc_matrix->mat(), MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
2799  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
2800  MAT_IGNORE_ZERO_ENTRIES,
2801  PETSC_TRUE));
2802  }
2803  }
2804 
2805  jacobianSetup();
2806 
2807  // Jacobian contributions from UOs - for now this is used for ray tracing
2808  // and ray kernels that contribute to the Jacobian (think line sources)
2809  std::vector<UserObject *> uos;
2811  .query()
2812  .condition<AttribSystem>("UserObject")
2813  .condition<AttribExecOns>(EXEC_PRE_KERNELS)
2814  .queryInto(uos);
2815  for (auto & uo : uos)
2816  uo->jacobianSetup();
2817  for (auto & uo : uos)
2818  {
2819  uo->initialize();
2820  uo->execute();
2821  uo->finalize();
2822  }
2823 
2824  // reinit scalar variables
2825  for (unsigned int tid = 0; tid < libMesh::n_threads(); tid++)
2827 
2828  PARALLEL_TRY
2829  {
2830  // We would like to compute ScalarKernels, block NodalKernels, FVFluxKernels, and mortar objects
2831  // up front because we want these included whether we are computing an ordinary Jacobian or a
2832  // Jacobian for determining variable scaling factors
2834 
2835  // Block restricted Nodal Kernels
2837  {
2840  Threads::parallel_reduce(range, cnkjt);
2841 
2842  unsigned int n_threads = libMesh::n_threads();
2843  for (unsigned int i = 0; i < n_threads;
2844  i++) // Add any cached jacobians that might be hanging around
2846  }
2847 
2849  if (_fe_problem.haveFV())
2850  {
2851  // the same loop works for both residual and jacobians because it keys
2852  // off of FEProblem's _currently_computing_jacobian parameter
2854  _fe_problem, this->number(), tags, /*on_displaced=*/false);
2856  Threads::parallel_reduce(faces, fvj);
2857  }
2859  displaced_problem && displaced_problem->haveFV())
2860  {
2862  _fe_problem, this->number(), tags, /*on_displaced=*/true);
2863  FVRange faces(displaced_problem->mesh().ownedFaceInfoBegin(),
2864  displaced_problem->mesh().ownedFaceInfoEnd());
2865  Threads::parallel_reduce(faces, fvr);
2866  }
2867 
2869 
2870  // Get our element range for looping over
2872 
2874  {
2875  // Only compute Jacobians corresponding to the diagonals of volumetric compute objects
2876  // because this typically gives us a good representation of the physics. NodalBCs and
2877  // Constraints can introduce dramatically different scales (often order unity).
2878  // IntegratedBCs and/or InterfaceKernels may use penalty factors. DGKernels may be ok, but
2879  // they are almost always used in conjunction with Kernels
2881  Threads::parallel_reduce(elem_range, cj);
2882  unsigned int n_threads = libMesh::n_threads();
2883  for (unsigned int i = 0; i < n_threads;
2884  i++) // Add any Jacobian contributions still hanging around
2886 
2887  // Check whether any exceptions were thrown and propagate this information for parallel
2888  // consistency before
2889  // 1) we do parallel communication when closing tagged matrices
2890  // 2) early returning before reaching our PARALLEL_CATCH below
2892 
2893  closeTaggedMatrices(tags);
2894 
2895  return;
2896  }
2897 
2898  switch (_fe_problem.coupling())
2899  {
2900  case Moose::COUPLING_DIAG:
2901  {
2903  Threads::parallel_reduce(elem_range, cj);
2904 
2905  unsigned int n_threads = libMesh::n_threads();
2906  for (unsigned int i = 0; i < n_threads;
2907  i++) // Add any Jacobian contributions still hanging around
2909 
2910  // Boundary restricted Nodal Kernels
2912  {
2915 
2916  Threads::parallel_reduce(bnd_range, cnkjt);
2917  unsigned int n_threads = libMesh::n_threads();
2918  for (unsigned int i = 0; i < n_threads;
2919  i++) // Add any cached jacobians that might be hanging around
2921  }
2922  }
2923  break;
2924 
2925  default:
2927  {
2929  Threads::parallel_reduce(elem_range, cj);
2930  unsigned int n_threads = libMesh::n_threads();
2931 
2932  for (unsigned int i = 0; i < n_threads; i++)
2934 
2935  // Boundary restricted Nodal Kernels
2937  {
2940 
2941  Threads::parallel_reduce(bnd_range, cnkjt);
2942  unsigned int n_threads = libMesh::n_threads();
2943  for (unsigned int i = 0; i < n_threads;
2944  i++) // Add any cached jacobians that might be hanging around
2946  }
2947  }
2948  break;
2949  }
2950 
2951  computeDiracContributions(tags, true);
2952 
2953  static bool first = true;
2954 
2955  // This adds zeroes into geometric coupling entries to ensure they stay in the matrix
2956  if ((_fe_problem.restoreOriginalNonzeroPattern() || first) &&
2958  {
2959  first = false;
2961 
2964  }
2965  }
2966  PARALLEL_CATCH;
2967 
2968  // Have no idea how to have constraints work
2969  // with the tag system
2970  PARALLEL_TRY
2971  {
2972  // Add in Jacobian contributions from other Constraints
2973  if (_fe_problem._has_constraints && tags.count(systemMatrixTag()))
2974  {
2975  // Some constraints need to be able to read values from the Jacobian, which requires that it
2976  // be closed/assembled
2977  auto & system_matrix = getMatrix(systemMatrixTag());
2978 #if PETSC_RELEASE_GREATER_EQUALS(3, 23, 0)
2979  SparseMatrix<Number> * view_jac_ptr;
2980  std::unique_ptr<SparseMatrix<Number>> hash_copy;
2981  if (system_matrix.use_hash_table())
2982  {
2983  hash_copy = libMesh::cast_ref<PetscMatrix<Number> &>(system_matrix).copy_from_hash();
2984  view_jac_ptr = hash_copy.get();
2985  }
2986  else
2987  view_jac_ptr = &system_matrix;
2988  auto & jacobian_to_view = *view_jac_ptr;
2989 #else
2990  auto & jacobian_to_view = system_matrix;
2991 #endif
2992  if (&jacobian_to_view == &system_matrix)
2993  system_matrix.close();
2994 
2995  // Nodal Constraints
2997 
2998  // Undisplaced Constraints
2999  constraintJacobians(jacobian_to_view, false);
3000 
3001  // Displaced Constraints
3003  constraintJacobians(jacobian_to_view, true);
3004  }
3005  }
3006  PARALLEL_CATCH;
3007 
3008  // We need to close the save_in variables on the aux system before NodalBCBases clear the dofs
3009  // on boundary nodes
3010  if (_has_diag_save_in)
3012 
3013  PARALLEL_TRY
3014  {
3015  MooseObjectWarehouse<NodalBCBase> * nbc_warehouse;
3016  // Select nodal kernels
3017  if (tags.size() == _fe_problem.numMatrixTags() || !tags.size())
3018  nbc_warehouse = &_nodal_bcs;
3019  else if (tags.size() == 1)
3020  nbc_warehouse = &(_nodal_bcs.getMatrixTagObjectWarehouse(*(tags.begin()), 0));
3021  else
3022  nbc_warehouse = &(_nodal_bcs.getMatrixTagsObjectWarehouse(tags, 0));
3023 
3024  if (nbc_warehouse->hasActiveObjects())
3025  {
3026  // We may be switching from add to set. Moreover, we rely on a call to MatZeroRows to enforce
3027  // the nodal boundary condition constraints which requires that the matrix be truly assembled
3028  // as opposed to just flushed. Consequently we can't do the following despite any desire to
3029  // keep our initial sparsity pattern honored (see https://gitlab.com/petsc/petsc/-/issues/852)
3030  //
3031  // flushTaggedMatrices(tags);
3032  closeTaggedMatrices(tags);
3033 
3034  // Cache the information about which BCs are coupled to which
3035  // variables, so we don't have to figure it out for each node.
3036  std::map<std::string, std::set<unsigned int>> bc_involved_vars;
3037  const std::set<BoundaryID> & all_boundary_ids = _mesh.getBoundaryIDs();
3038  for (const auto & bid : all_boundary_ids)
3039  {
3040  // Get reference to all the NodalBCs for this ID. This is only
3041  // safe if there are NodalBCBases there to be gotten...
3042  if (nbc_warehouse->hasActiveBoundaryObjects(bid))
3043  {
3044  const auto & bcs = nbc_warehouse->getActiveBoundaryObjects(bid);
3045  for (const auto & bc : bcs)
3046  {
3047  const std::vector<MooseVariableFEBase *> & coupled_moose_vars =
3048  bc->getCoupledMooseVars();
3049 
3050  // Create the set of "involved" MOOSE nonlinear vars, which includes all coupled vars
3051  // and the BC's own variable
3052  std::set<unsigned int> & var_set = bc_involved_vars[bc->name()];
3053  for (const auto & coupled_var : coupled_moose_vars)
3054  if (coupled_var->kind() == Moose::VAR_SOLVER)
3055  var_set.insert(coupled_var->number());
3056 
3057  var_set.insert(bc->variable().number());
3058  }
3059  }
3060  }
3061 
3062  // reinit scalar variables again. This reinit does not re-fill any of the scalar variable
3063  // solution arrays because that was done above. It only will reorder the derivative
3064  // information for AD calculations to be suitable for NodalBC calculations
3065  for (unsigned int tid = 0; tid < libMesh::n_threads(); tid++)
3066  _fe_problem.reinitScalars(tid, true);
3067 
3068  // Get variable coupling list. We do all the NodalBCBase stuff on
3069  // thread 0... The couplingEntries() data structure determines
3070  // which variables are "coupled" as far as the preconditioner is
3071  // concerned, not what variables a boundary condition specifically
3072  // depends on.
3073  auto & coupling_entries = _fe_problem.couplingEntries(/*_tid=*/0, this->number());
3074 
3075  // Compute Jacobians for NodalBCBases
3077  for (const auto & bnode : bnd_nodes)
3078  {
3079  BoundaryID boundary_id = bnode->_bnd_id;
3080  Node * node = bnode->_node;
3081 
3082  if (nbc_warehouse->hasActiveBoundaryObjects(boundary_id) &&
3083  node->processor_id() == processor_id())
3084  {
3085  _fe_problem.reinitNodeFace(node, boundary_id, 0);
3086 
3087  const auto & bcs = nbc_warehouse->getActiveBoundaryObjects(boundary_id);
3088  for (const auto & bc : bcs)
3089  {
3090  // Get the set of involved MOOSE vars for this BC
3091  std::set<unsigned int> & var_set = bc_involved_vars[bc->name()];
3092 
3093  // Loop over all the variables whose Jacobian blocks are
3094  // actually being computed, call computeOffDiagJacobian()
3095  // for each one which is actually coupled (otherwise the
3096  // value is zero.)
3097  for (const auto & it : coupling_entries)
3098  {
3099  unsigned int ivar = it.first->number(), jvar = it.second->number();
3100 
3101  // We are only going to call computeOffDiagJacobian() if:
3102  // 1.) the BC's variable is ivar
3103  // 2.) jvar is "involved" with the BC (including jvar==ivar), and
3104  // 3.) the BC should apply.
3105  if ((bc->variable().number() == ivar) && var_set.count(jvar) && bc->shouldApply())
3106  bc->computeOffDiagJacobian(jvar);
3107  }
3108 
3109  const auto & coupled_scalar_vars = bc->getCoupledMooseScalarVars();
3110  for (const auto & jvariable : coupled_scalar_vars)
3111  if (hasScalarVariable(jvariable->name()))
3112  bc->computeOffDiagJacobianScalar(jvariable->number());
3113  }
3114  }
3115  } // end loop over boundary nodes
3116 
3117  // Set the cached NodalBCBase values in the Jacobian matrix
3119  }
3120  }
3121  PARALLEL_CATCH;
3122 
3123  closeTaggedMatrices(tags);
3124 
3125  // We need to close the save_in variables on the aux system before NodalBCBases clear the dofs
3126  // on boundary nodes
3129 
3130  if (hasDiagSaveIn())
3132 
3133  // Accumulate the occurrence of solution invalid warnings for the current iteration cumulative
3134  // counters
3137 }
3138 
3139 void
3141 {
3142  _nl_matrix_tags.clear();
3143 
3144  auto & tags = _fe_problem.getMatrixTags();
3145 
3146  for (auto & tag : tags)
3147  _nl_matrix_tags.insert(tag.second);
3148 
3149  computeJacobian(jacobian, _nl_matrix_tags);
3150 }
3151 
3152 void
3153 NonlinearSystemBase::computeJacobian(SparseMatrix<Number> & jacobian, const std::set<TagID> & tags)
3154 {
3156 
3157  computeJacobianTags(tags);
3158 
3160 }
3161 
3162 void
3163 NonlinearSystemBase::computeJacobianTags(const std::set<TagID> & tags)
3164 {
3165  TIME_SECTION("computeJacobianTags", 5);
3166 
3167  FloatingPointExceptionGuard fpe_guard(_app);
3168 
3169  try
3170  {
3172  }
3173  catch (MooseException & e)
3174  {
3175  // The buck stops here, we have already handled the exception by
3176  // calling stopSolve(), it is now up to PETSc to return a
3177  // "diverged" reason during the next solve.
3178  }
3179 }
3180 
3181 void
3183 {
3184  _nl_matrix_tags.clear();
3185 
3186  auto & tags = _fe_problem.getMatrixTags();
3187  for (auto & tag : tags)
3188  _nl_matrix_tags.insert(tag.second);
3189 
3191 }
3192 
3193 void
3195  const std::set<TagID> & tags)
3196 {
3197  TIME_SECTION("computeJacobianBlocks", 3);
3198  FloatingPointExceptionGuard fpe_guard(_app);
3199 
3200  for (unsigned int i = 0; i < blocks.size(); i++)
3201  {
3202  SparseMatrix<Number> & jacobian = blocks[i]->_jacobian;
3203 
3204  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
3205  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
3206  PETSC_TRUE));
3208  LibmeshPetscCall(MatSetOption(static_cast<PetscMatrix<Number> &>(jacobian).mat(),
3209  MAT_NEW_NONZERO_ALLOCATION_ERR,
3210  PETSC_TRUE));
3211 
3212  jacobian.zero();
3213  }
3214 
3215  for (unsigned int tid = 0; tid < libMesh::n_threads(); tid++)
3217 
3218  PARALLEL_TRY
3219  {
3222  Threads::parallel_reduce(elem_range, cjb);
3223  }
3224  PARALLEL_CATCH;
3225 
3226  for (unsigned int i = 0; i < blocks.size(); i++)
3227  blocks[i]->_jacobian.close();
3228 
3229  for (unsigned int i = 0; i < blocks.size(); i++)
3230  {
3231  libMesh::System & precond_system = blocks[i]->_precond_system;
3232  SparseMatrix<Number> & jacobian = blocks[i]->_jacobian;
3233 
3234  unsigned int ivar = blocks[i]->_ivar;
3235  unsigned int jvar = blocks[i]->_jvar;
3236 
3237  // Dirichlet BCs
3238  std::vector<numeric_index_type> zero_rows;
3239  PARALLEL_TRY
3240  {
3242  for (const auto & bnode : bnd_nodes)
3243  {
3244  BoundaryID boundary_id = bnode->_bnd_id;
3245  Node * node = bnode->_node;
3246 
3247  if (_nodal_bcs.hasActiveBoundaryObjects(boundary_id))
3248  {
3249  const auto & bcs = _nodal_bcs.getActiveBoundaryObjects(boundary_id);
3250 
3251  if (node->processor_id() == processor_id())
3252  {
3253  _fe_problem.reinitNodeFace(node, boundary_id, 0);
3254 
3255  for (const auto & bc : bcs)
3256  if (bc->variable().number() == ivar && bc->shouldApply())
3257  {
3258  // The first zero is for the variable number... there is only one variable in
3259  // each mini-system The second zero only works with Lagrange elements!
3260  zero_rows.push_back(node->dof_number(precond_system.number(), 0, 0));
3261  }
3262  }
3263  }
3264  }
3265  }
3266  PARALLEL_CATCH;
3267 
3268  jacobian.close();
3269 
3270  // This zeroes the rows corresponding to Dirichlet BCs and puts a 1.0 on the diagonal
3271  if (ivar == jvar)
3272  jacobian.zero_rows(zero_rows, 1.0);
3273  else
3274  jacobian.zero_rows(zero_rows, 0.0);
3275 
3276  jacobian.close();
3277  }
3278 }
3279 
3280 void
3282 {
3289  _kernels.updateActive(tid);
3291  if (tid == 0)
3292  {
3299  }
3300 }
3301 
3302 Real
3304  const NumericVector<Number> & update)
3305 {
3306  // Default to no damping
3307  Real damping = 1.0;
3308  bool has_active_dampers = false;
3309 
3310  try
3311  {
3313  {
3314  PARALLEL_TRY
3315  {
3316  TIME_SECTION("computeDampers", 3, "Computing Dampers");
3317  has_active_dampers = true;
3320  Threads::parallel_reduce(_fe_problem.getCurrentAlgebraicElementRange(), cid);
3321  damping = std::min(cid.damping(), damping);
3322  }
3323  PARALLEL_CATCH;
3324  }
3325 
3327  {
3328  PARALLEL_TRY
3329  {
3330  TIME_SECTION("computeDamping::element", 3, "Computing Element Damping");
3331 
3332  has_active_dampers = true;
3335  Threads::parallel_reduce(_fe_problem.getCurrentAlgebraicNodeRange(), cndt);
3336  damping = std::min(cndt.damping(), damping);
3337  }
3338  PARALLEL_CATCH;
3339  }
3340 
3342  {
3343  PARALLEL_TRY
3344  {
3345  TIME_SECTION("computeDamping::general", 3, "Computing General Damping");
3346 
3347  has_active_dampers = true;
3348  const auto & gdampers = _general_dampers.getActiveObjects();
3349  for (const auto & damper : gdampers)
3350  {
3351  Real gd_damping = damper->computeDamping(solution, update);
3352  try
3353  {
3354  damper->checkMinDamping(gd_damping);
3355  }
3356  catch (MooseException & e)
3357  {
3359  }
3360  damping = std::min(gd_damping, damping);
3361  }
3362  }
3363  PARALLEL_CATCH;
3364  }
3365  }
3366  catch (MooseException & e)
3367  {
3368  // The buck stops here, we have already handled the exception by
3369  // calling stopSolve(), it is now up to PETSc to return a
3370  // "diverged" reason during the next solve.
3371  }
3372 
3373  _communicator.min(damping);
3374 
3375  if (has_active_dampers && damping < 1.0)
3376  _console << " Damping factor: " << damping << std::endl;
3377 
3378  return damping;
3379 }
3380 
3381 void
3382 NonlinearSystemBase::computeDiracContributions(const std::set<TagID> & tags, bool is_jacobian)
3383 {
3385 
3386  std::set<const Elem *> dirac_elements;
3387 
3389  {
3390  TIME_SECTION("computeDirac", 3, "Computing DiracKernels");
3391 
3392  // TODO: Need a threading fix... but it's complicated!
3393  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); ++tid)
3394  {
3395  const auto & dkernels = _dirac_kernels.getActiveObjects(tid);
3396  for (const auto & dkernel : dkernels)
3397  {
3398  dkernel->clearPoints();
3399  dkernel->addPoints();
3400  }
3401  }
3402 
3403  ComputeDiracThread cd(_fe_problem, tags, is_jacobian);
3404 
3405  _fe_problem.getDiracElements(dirac_elements);
3406 
3407  DistElemRange range(dirac_elements.begin(), dirac_elements.end(), 1);
3408  // TODO: Make Dirac work thread!
3409  // Threads::parallel_reduce(range, cd);
3410 
3411  cd(range);
3412  }
3413 }
3414 
3417 {
3418  if (!_residual_copy.get())
3420 
3421  return *_residual_copy;
3422 }
3423 
3426 {
3427  _need_residual_ghosted = true;
3428  if (!_residual_ghosted)
3429  {
3430  // The first time we realize we need a ghosted residual vector,
3431  // we add it.
3432  _residual_ghosted = &addVector("residual_ghosted", false, GHOSTED);
3433 
3434  // If we've already realized we need time and/or non-time
3435  // residual vectors, but we haven't yet realized they need to be
3436  // ghosted, fix that now.
3437  //
3438  // If an application changes its mind, the libMesh API lets us
3439  // change the vector.
3440  if (_Re_time)
3441  {
3442  const auto vector_name = _subproblem.vectorTagName(_Re_time_tag);
3443  _Re_time = &system().add_vector(vector_name, false, GHOSTED);
3444  }
3445  if (_Re_non_time)
3446  {
3447  const auto vector_name = _subproblem.vectorTagName(_Re_non_time_tag);
3448  _Re_non_time = &system().add_vector(vector_name, false, GHOSTED);
3449  }
3450  }
3451  return *_residual_ghosted;
3452 }
3453 
3454 void
3456  std::vector<dof_id_type> & n_nz,
3457  std::vector<dof_id_type> & n_oz)
3458 {
3460  {
3462 
3463  std::unordered_map<dof_id_type, std::vector<dof_id_type>> graph;
3464 
3466 
3469  graph);
3470 
3471  const dof_id_type first_dof_on_proc = dofMap().first_dof(processor_id());
3472  const dof_id_type end_dof_on_proc = dofMap().end_dof(processor_id());
3473 
3474  // The total number of dofs on and off processor
3475  const dof_id_type n_dofs_on_proc = dofMap().n_local_dofs();
3476  const dof_id_type n_dofs_not_on_proc = dofMap().n_dofs() - dofMap().n_local_dofs();
3477 
3478  for (const auto & git : graph)
3479  {
3480  dof_id_type dof = git.first;
3481  dof_id_type local_dof = dof - first_dof_on_proc;
3482 
3483  if (dof < first_dof_on_proc || dof >= end_dof_on_proc)
3484  continue;
3485 
3486  const auto & row = git.second;
3487 
3488  SparsityPattern::Row & sparsity_row = sparsity[local_dof];
3489 
3490  unsigned int original_row_length = sparsity_row.size();
3491 
3492  sparsity_row.insert(sparsity_row.end(), row.begin(), row.end());
3493 
3494  SparsityPattern::sort_row(
3495  sparsity_row.begin(), sparsity_row.begin() + original_row_length, sparsity_row.end());
3496 
3497  // Fix up nonzero arrays
3498  for (const auto & coupled_dof : row)
3499  {
3500  if (coupled_dof < first_dof_on_proc || coupled_dof >= end_dof_on_proc)
3501  {
3502  if (n_oz[local_dof] < n_dofs_not_on_proc)
3503  n_oz[local_dof]++;
3504  }
3505  else
3506  {
3507  if (n_nz[local_dof] < n_dofs_on_proc)
3508  n_nz[local_dof]++;
3509  }
3510  }
3511  }
3512  }
3513 }
3514 
3515 void
3517 {
3518  *_u_dot = u_dot;
3519 }
3520 
3521 void
3523 {
3524  *_u_dotdot = u_dotdot;
3525 }
3526 
3527 void
3529 {
3530  *_u_dot_old = u_dot_old;
3531 }
3532 
3533 void
3535 {
3536  *_u_dotdot_old = u_dotdot_old;
3537 }
3538 
3539 void
3540 NonlinearSystemBase::setPreconditioner(std::shared_ptr<MoosePreconditioner> pc)
3541 {
3542  if (_preconditioner.get() != nullptr)
3543  mooseError("More than one active Preconditioner detected");
3544 
3545  _preconditioner = pc;
3546 }
3547 
3548 MoosePreconditioner const *
3550 {
3551  return _preconditioner.get();
3552 }
3553 
3554 void
3556 {
3557  _increment_vec = &_sys.add_vector("u_increment", true, GHOSTED);
3558 }
3559 
3560 void
3562  const std::set<MooseVariable *> & damped_vars)
3563 {
3564  for (const auto & var : damped_vars)
3565  var->computeIncrementAtQps(*_increment_vec);
3566 }
3567 
3568 void
3570  const std::set<MooseVariable *> & damped_vars)
3571 {
3572  for (const auto & var : damped_vars)
3573  var->computeIncrementAtNode(*_increment_vec);
3574 }
3575 
3576 void
3577 NonlinearSystemBase::checkKernelCoverage(const std::set<SubdomainID> & mesh_subdomains) const
3578 {
3579  // Obtain all blocks and variables covered by all kernels
3580  std::set<SubdomainID> input_subdomains;
3581  std::set<std::string> kernel_variables;
3582 
3583  bool global_kernels_exist = false;
3584  global_kernels_exist |= _scalar_kernels.hasActiveObjects();
3585  global_kernels_exist |= _nodal_kernels.hasActiveObjects();
3586 
3587  _kernels.subdomainsCovered(input_subdomains, kernel_variables);
3588  _dg_kernels.subdomainsCovered(input_subdomains, kernel_variables);
3589  _nodal_kernels.subdomainsCovered(input_subdomains, kernel_variables);
3590  _scalar_kernels.subdomainsCovered(input_subdomains, kernel_variables);
3591  _constraints.subdomainsCovered(input_subdomains, kernel_variables);
3592 
3593  if (_fe_problem.haveFV())
3594  {
3595  std::vector<FVElementalKernel *> fv_elemental_kernels;
3597  .query()
3598  .template condition<AttribSystem>("FVElementalKernel")
3599  .queryInto(fv_elemental_kernels);
3600 
3601  for (auto fv_kernel : fv_elemental_kernels)
3602  {
3603  if (fv_kernel->blockRestricted())
3604  for (auto block_id : fv_kernel->blockIDs())
3605  input_subdomains.insert(block_id);
3606  else
3607  global_kernels_exist = true;
3608  kernel_variables.insert(fv_kernel->variable().name());
3609 
3610  // Check for lagrange multiplier
3611  if (dynamic_cast<FVScalarLagrangeMultiplierConstraint *>(fv_kernel))
3612  kernel_variables.insert(dynamic_cast<FVScalarLagrangeMultiplierConstraint *>(fv_kernel)
3613  ->lambdaVariable()
3614  .name());
3615  }
3616 
3617  std::vector<FVFluxKernel *> fv_flux_kernels;
3619  .query()
3620  .template condition<AttribSystem>("FVFluxKernel")
3621  .queryInto(fv_flux_kernels);
3622 
3623  for (auto fv_kernel : fv_flux_kernels)
3624  {
3625  if (fv_kernel->blockRestricted())
3626  for (auto block_id : fv_kernel->blockIDs())
3627  input_subdomains.insert(block_id);
3628  else
3629  global_kernels_exist = true;
3630  kernel_variables.insert(fv_kernel->variable().name());
3631  }
3632 
3633  std::vector<FVInterfaceKernel *> fv_interface_kernels;
3635  .query()
3636  .template condition<AttribSystem>("FVInterfaceKernel")
3637  .queryInto(fv_interface_kernels);
3638 
3639  for (auto fvik : fv_interface_kernels)
3640  if (auto scalar_fvik = dynamic_cast<FVScalarLagrangeMultiplierInterface *>(fvik))
3641  kernel_variables.insert(scalar_fvik->lambdaVariable().name());
3642 
3643  std::vector<FVFluxBC *> fv_flux_bcs;
3645  .query()
3646  .template condition<AttribSystem>("FVFluxBC")
3647  .queryInto(fv_flux_bcs);
3648 
3649  for (auto fvbc : fv_flux_bcs)
3650  if (auto scalar_fvbc = dynamic_cast<FVBoundaryScalarLagrangeMultiplierConstraint *>(fvbc))
3651  kernel_variables.insert(scalar_fvbc->lambdaVariable().name());
3652  }
3653 
3654  // Check kernel coverage of subdomains (blocks) in your mesh
3655  if (!global_kernels_exist)
3656  {
3657  std::set<SubdomainID> difference;
3658  std::set_difference(mesh_subdomains.begin(),
3659  mesh_subdomains.end(),
3660  input_subdomains.begin(),
3661  input_subdomains.end(),
3662  std::inserter(difference, difference.end()));
3663 
3664  // there supposed to be no kernels on this lower-dimensional subdomain
3665  for (const auto & id : _mesh.interiorLowerDBlocks())
3666  difference.erase(id);
3667  for (const auto & id : _mesh.boundaryLowerDBlocks())
3668  difference.erase(id);
3669 
3670  if (!difference.empty())
3671  {
3672  std::vector<SubdomainID> difference_vec =
3673  std::vector<SubdomainID>(difference.begin(), difference.end());
3674  std::vector<SubdomainName> difference_names = _mesh.getSubdomainNames(difference_vec);
3675  std::stringstream missing_block_names;
3676  std::copy(difference_names.begin(),
3677  difference_names.end(),
3678  std::ostream_iterator<std::string>(missing_block_names, " "));
3679  std::stringstream missing_block_ids;
3680  std::copy(difference.begin(),
3681  difference.end(),
3682  std::ostream_iterator<unsigned int>(missing_block_ids, " "));
3683 
3684  mooseError("Each subdomain must contain at least one Kernel.\nThe following block(s) lack an "
3685  "active kernel: " +
3686  missing_block_names.str(),
3687  " (ids: ",
3688  missing_block_ids.str(),
3689  ")");
3690  }
3691  }
3692 
3693  // Check kernel use of variables
3694  std::set<VariableName> variables(getVariableNames().begin(), getVariableNames().end());
3695 
3696  std::set<VariableName> difference;
3697  std::set_difference(variables.begin(),
3698  variables.end(),
3699  kernel_variables.begin(),
3700  kernel_variables.end(),
3701  std::inserter(difference, difference.end()));
3702 
3703  // skip checks for varaibles defined on lower-dimensional subdomain
3704  std::set<VariableName> vars(difference);
3705  for (auto & var_name : vars)
3706  {
3707  auto blks = getSubdomainsForVar(var_name);
3708  for (const auto & id : blks)
3709  if (_mesh.interiorLowerDBlocks().count(id) > 0 || _mesh.boundaryLowerDBlocks().count(id) > 0)
3710  difference.erase(var_name);
3711  }
3712 
3713  if (!difference.empty())
3714  {
3715  std::stringstream missing_kernel_vars;
3716  std::copy(difference.begin(),
3717  difference.end(),
3718  std::ostream_iterator<std::string>(missing_kernel_vars, " "));
3719  mooseError("Each variable must be referenced by at least one active Kernel.\nThe following "
3720  "variable(s) lack an active kernel: " +
3721  missing_kernel_vars.str());
3722  }
3723 }
3724 
3725 bool
3727 {
3728  auto & time_kernels = _kernels.getVectorTagObjectWarehouse(timeVectorTag(), 0);
3729 
3730  return time_kernels.hasActiveObjects();
3731 }
3732 
3733 std::vector<std::string>
3735 {
3736  std::vector<std::string> variable_names;
3737  const auto & time_kernels = _kernels.getVectorTagObjectWarehouse(timeVectorTag(), 0);
3738  if (time_kernels.hasActiveObjects())
3739  for (const auto & kernel : time_kernels.getObjects())
3740  variable_names.push_back(kernel->variable().name());
3741 
3742  return variable_names;
3743 }
3744 
3745 bool
3747 {
3748  return _integrated_bcs.hasActiveBoundaryObjects(bnd_id, tid);
3749 }
3750 
3751 bool
3753 {
3754  return _interface_kernels.hasActiveBoundaryObjects(bnd_id, tid);
3755 }
3756 
3757 bool
3759  THREAD_ID /*tid*/) const
3760 {
3761  return _doing_dg;
3762 }
3763 
3764 bool
3766 {
3767  return _doing_dg;
3768 }
3769 
3770 void
3772 {
3775 }
3776 
3777 void
3779  const std::set<TagID> & vector_tags,
3780  const std::set<TagID> & matrix_tags)
3781 {
3782  parallel_object_only();
3783 
3784  try
3785  {
3786  for (auto & map_pr : _undisplaced_mortar_functors)
3787  map_pr.second(compute_type, vector_tags, matrix_tags);
3788 
3789  for (auto & map_pr : _displaced_mortar_functors)
3790  map_pr.second(compute_type, vector_tags, matrix_tags);
3791  }
3792  catch (MetaPhysicL::LogicError &)
3793  {
3794  mooseError(
3795  "We caught a MetaPhysicL error in NonlinearSystemBase::mortarConstraints. This is very "
3796  "likely due to AD not having a sufficiently large derivative container size. Please run "
3797  "MOOSE configure with the '--with-derivative-size=<n>' option");
3798  }
3799 }
3800 
3801 void
3803 {
3804  if (_auto_scaling_initd)
3805  return;
3806 
3807  // Want the libMesh count of variables, not MOOSE, e.g. I don't care about array variable counts
3808  const auto n_vars = system().n_vars();
3809 
3810  if (_scaling_group_variables.empty())
3811  {
3812  _var_to_group_var.reserve(n_vars);
3814 
3815  for (const auto var_number : make_range(n_vars))
3816  _var_to_group_var.emplace(var_number, var_number);
3817  }
3818  else
3819  {
3820  std::set<unsigned int> var_numbers, var_numbers_covered, var_numbers_not_covered;
3821  for (const auto var_number : make_range(n_vars))
3822  var_numbers.insert(var_number);
3823 
3825 
3826  for (const auto group_index : index_range(_scaling_group_variables))
3827  for (const auto & var_name : _scaling_group_variables[group_index])
3828  {
3829  if (!hasVariable(var_name) && !hasScalarVariable(var_name))
3830  mooseError("'",
3831  var_name,
3832  "', provided to the 'scaling_group_variables' parameter, does not exist in "
3833  "the nonlinear system.");
3834 
3835  const MooseVariableBase & var =
3836  hasVariable(var_name)
3837  ? static_cast<MooseVariableBase &>(getVariable(0, var_name))
3838  : static_cast<MooseVariableBase &>(getScalarVariable(0, var_name));
3839  auto map_pair = _var_to_group_var.emplace(var.number(), group_index);
3840  if (!map_pair.second)
3841  mooseError("Variable ", var_name, " is contained in multiple scaling grouplings");
3842  var_numbers_covered.insert(var.number());
3843  }
3844 
3845  std::set_difference(var_numbers.begin(),
3846  var_numbers.end(),
3847  var_numbers_covered.begin(),
3848  var_numbers_covered.end(),
3849  std::inserter(var_numbers_not_covered, var_numbers_not_covered.begin()));
3850 
3851  _num_scaling_groups = _scaling_group_variables.size() + var_numbers_not_covered.size();
3852 
3853  auto index = static_cast<unsigned int>(_scaling_group_variables.size());
3854  for (auto var_number : var_numbers_not_covered)
3855  _var_to_group_var.emplace(var_number, index++);
3856  }
3857 
3858  _variable_autoscaled.resize(n_vars, true);
3859  const auto & number_to_var_map = _vars[0].numberToVariableMap();
3860 
3862  for (const auto i : index_range(_variable_autoscaled))
3863  if (std::find(_ignore_variables_for_autoscaling.begin(),
3865  libmesh_map_find(number_to_var_map, i)->name()) !=
3867  _variable_autoscaled[i] = false;
3868 
3869  _auto_scaling_initd = true;
3870 }
3871 
3872 bool
3874 {
3876  return true;
3877 
3878  _console << "\nPerforming automatic scaling calculation\n" << std::endl;
3879 
3880  TIME_SECTION("computeScaling", 3, "Computing Automatic Scaling");
3881 
3882  // It's funny but we need to assemble our vector of scaling factors here otherwise we will be
3883  // applying scaling factors of 0 during Assembly of our scaling Jacobian
3885 
3886  // container for repeated access of element global dof indices
3887  std::vector<dof_id_type> dof_indices;
3888 
3889  if (!_auto_scaling_initd)
3890  setupScalingData();
3891 
3892  std::vector<Real> inverse_scaling_factors(_num_scaling_groups, 0);
3893  std::vector<Real> resid_inverse_scaling_factors(_num_scaling_groups, 0);
3894  std::vector<Real> jac_inverse_scaling_factors(_num_scaling_groups, 0);
3895  auto & dof_map = dofMap();
3896 
3897  // what types of scaling do we want?
3898  bool jac_scaling = _resid_vs_jac_scaling_param < 1. - TOLERANCE;
3899  bool resid_scaling = _resid_vs_jac_scaling_param > TOLERANCE;
3900 
3901  const NumericVector<Number> & scaling_residual = RHS();
3902 
3903  if (jac_scaling)
3904  {
3905  // if (!_auto_scaling_initd)
3906  // We need to reinit this when the number of dofs changes
3907  // but there is no good way to track that
3908  // In theory, it is the job of libmesh system to track this,
3909  // but this special matrix is not owned by libMesh system
3910  // Let us reinit eveytime since it is not expensive
3911  {
3912  auto init_vector = NumericVector<Number>::build(this->comm());
3913  init_vector->init(system().n_dofs(), system().n_local_dofs(), /*fast=*/false, PARALLEL);
3914 
3915  _scaling_matrix->clear();
3916  _scaling_matrix->init(*init_vector);
3917  }
3918 
3920  // Dispatch to derived classes to ensure that we use the correct matrix tag
3923  }
3924 
3925  if (resid_scaling)
3926  {
3929  // Dispatch to derived classes to ensure that we use the correct vector tag
3933  }
3934 
3935  // Did something bad happen during residual/Jacobian scaling computation?
3937  return false;
3938 
3939  auto examine_dof_indices = [this,
3940  jac_scaling,
3941  resid_scaling,
3942  &dof_map,
3943  &jac_inverse_scaling_factors,
3944  &resid_inverse_scaling_factors,
3945  &scaling_residual](const auto & dof_indices, const auto var_number)
3946  {
3947  for (auto dof_index : dof_indices)
3948  if (dof_map.local_index(dof_index))
3949  {
3950  if (jac_scaling)
3951  {
3952  // For now we will use the diagonal for determining scaling
3953  auto mat_value = (*_scaling_matrix)(dof_index, dof_index);
3954  auto & factor = jac_inverse_scaling_factors[_var_to_group_var[var_number]];
3955  factor = std::max(factor, std::abs(mat_value));
3956  }
3957  if (resid_scaling)
3958  {
3959  auto vec_value = scaling_residual(dof_index);
3960  auto & factor = resid_inverse_scaling_factors[_var_to_group_var[var_number]];
3961  factor = std::max(factor, std::abs(vec_value));
3962  }
3963  }
3964  };
3965 
3966  // Compute our scaling factors for the spatial field variables
3967  for (const auto & elem : _fe_problem.getCurrentAlgebraicElementRange())
3968  for (const auto i : make_range(system().n_vars()))
3970  {
3971  dof_map.dof_indices(elem, dof_indices, i);
3972  examine_dof_indices(dof_indices, i);
3973  }
3974 
3975  for (const auto i : make_range(system().n_vars()))
3976  if (_variable_autoscaled[i] && system().variable_type(i).family == SCALAR)
3977  {
3978  dof_map.SCALAR_dof_indices(dof_indices, i);
3979  examine_dof_indices(dof_indices, i);
3980  }
3981 
3982  if (resid_scaling)
3983  _communicator.max(resid_inverse_scaling_factors);
3984  if (jac_scaling)
3985  _communicator.max(jac_inverse_scaling_factors);
3986 
3987  if (jac_scaling && resid_scaling)
3988  for (MooseIndex(inverse_scaling_factors) i = 0; i < inverse_scaling_factors.size(); ++i)
3989  {
3990  // Be careful not to take log(0)
3991  if (!resid_inverse_scaling_factors[i])
3992  {
3993  if (!jac_inverse_scaling_factors[i])
3994  inverse_scaling_factors[i] = 1;
3995  else
3996  inverse_scaling_factors[i] = jac_inverse_scaling_factors[i];
3997  }
3998  else if (!jac_inverse_scaling_factors[i])
3999  // We know the resid is not zero
4000  inverse_scaling_factors[i] = resid_inverse_scaling_factors[i];
4001  else
4002  inverse_scaling_factors[i] =
4003  std::exp(_resid_vs_jac_scaling_param * std::log(resid_inverse_scaling_factors[i]) +
4004  (1 - _resid_vs_jac_scaling_param) * std::log(jac_inverse_scaling_factors[i]));
4005  }
4006  else if (jac_scaling)
4007  inverse_scaling_factors = jac_inverse_scaling_factors;
4008  else if (resid_scaling)
4009  inverse_scaling_factors = resid_inverse_scaling_factors;
4010  else
4011  mooseError("We shouldn't be calling this routine if we're not performing any scaling");
4012 
4013  // We have to make sure that our scaling values are not zero
4014  for (auto & scaling_factor : inverse_scaling_factors)
4015  if (scaling_factor == 0)
4016  scaling_factor = 1;
4017 
4018  // Now flatten the group scaling factors to the individual variable scaling factors
4019  std::vector<Real> flattened_inverse_scaling_factors(system().n_vars());
4020  for (const auto i : index_range(flattened_inverse_scaling_factors))
4021  flattened_inverse_scaling_factors[i] = inverse_scaling_factors[_var_to_group_var[i]];
4022 
4023  // Now set the scaling factors for the variables
4024  applyScalingFactors(flattened_inverse_scaling_factors);
4026  displaced_problem->systemBaseNonlinear(number()).applyScalingFactors(
4027  flattened_inverse_scaling_factors);
4028 
4029  _computed_scaling = true;
4030  return true;
4031 }
4032 
4033 void
4035 {
4036  if (!hasVector("scaling_factors"))
4037  // No variables have indicated they need scaling
4038  return;
4039 
4040  auto & scaling_vector = getVector("scaling_factors");
4041 
4042  const auto & lm_mesh = _mesh.getMesh();
4043  const auto & dof_map = dofMap();
4044 
4045  const auto & field_variables = _vars[0].fieldVariables();
4046  const auto & scalar_variables = _vars[0].scalars();
4047 
4048  std::vector<dof_id_type> dof_indices;
4049 
4050  for (const Elem * const elem :
4051  as_range(lm_mesh.active_local_elements_begin(), lm_mesh.active_local_elements_end()))
4052  for (const auto * const field_var : field_variables)
4053  {
4054  const auto & factors = field_var->arrayScalingFactor();
4055  for (const auto i : make_range(field_var->count()))
4056  {
4057  dof_map.dof_indices(elem, dof_indices, field_var->number() + i);
4058  for (const auto dof : dof_indices)
4059  scaling_vector.set(dof, factors[i]);
4060  }
4061  }
4062 
4063  for (const auto * const scalar_var : scalar_variables)
4064  {
4065  mooseAssert(scalar_var->count() == 1,
4066  "Scalar variables should always have only one component.");
4067  dof_map.SCALAR_dof_indices(dof_indices, scalar_var->number());
4068  for (const auto dof : dof_indices)
4069  scaling_vector.set(dof, scalar_var->scalingFactor());
4070  }
4071 
4072  // Parallel assemble
4073  scaling_vector.close();
4074 
4075  if (auto * displaced_problem = _fe_problem.getDisplacedProblem().get())
4076  // copy into the corresponding displaced system vector because they should be the exact same
4077  displaced_problem->systemBaseNonlinear(number()).getVector("scaling_factors") = scaling_vector;
4078 }
4079 
4080 bool
4082 {
4083  // Clear the iteration counters
4084  _current_l_its.clear();
4085  _current_nl_its = 0;
4086 
4087  // Initialize the solution vector using a predictor and known values from nodal bcs
4089 
4090  // Now that the initial solution has ben set, potentially perform a residual/Jacobian evaluation
4091  // to determine variable scaling factors
4092  if (_automatic_scaling)
4093  {
4094  const bool scaling_succeeded = computeScaling();
4095  if (!scaling_succeeded)
4096  return false;
4097  }
4098 
4099  // We do not know a priori what variable a global degree of freedom corresponds to, so we need a
4100  // map from global dof to scaling factor. We just use a ghosted NumericVector for that mapping
4102 
4103  return true;
4104 }
4105 
4106 void
4108 {
4109  if (matrixFromColoring())
4110  LibmeshPetscCall(MatFDColoringDestroy(&_fdcoloring));
4111 }
4112 
4115 {
4116  if (!_fsp)
4117  mooseError("No field split preconditioner is present for this system");
4118 
4119  return *_fsp;
4120 }
std::string name(const ElemQuality q)
std::vector< std::shared_ptr< TimeIntegrator > > _time_integrators
Time integrator.
Definition: SystemBase.h:1049
virtual void setSolutionUDotDotOld(const NumericVector< Number > &u_dotdot_old)
virtual void reinitNeighborPhys(const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > &physical_points, const THREAD_ID tid)=0
virtual void residualSetup(THREAD_ID tid=0) const
NumericVector< Number > & getResidualTimeVector()
Return a numeric vector that is associated with the time tag.
void setActiveMaterialProperties(const std::unordered_set< unsigned int > &mat_prop_ids, const THREAD_ID tid)
Record and set the material properties required by the current computing thread.
MooseObjectTagWarehouse< NodalKernelBase > _nodal_kernels
NodalKernels for each thread.
NumericVector< Number > * _Re_time
residual vector for time contributions
void computeJacobianBlocks(std::vector< JacobianBlock *> &blocks)
Computes several Jacobian blocks simultaneously, summing their contributions into smaller preconditio...
virtual void insert(const T *v, const std::vector< numeric_index_type > &dof_indices)
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
Definition: EigenADReal.h:42
TagID _Re_time_tag
Tag for time contribution residual.
void allgather(const T &send_data, std::vector< T, A > &recv_data) const
unsigned int size(THREAD_ID tid=0) const
Return how many kernels we store in the current warehouse.
std::map< std::pair< BoundaryID, BoundaryID >, PenetrationLocator * > _penetration_locators
dof_id_type end_dof(const processor_id_type proc) const
bool empty() const
virtual void addKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds a kernel.
virtual void setSolutionUDotDot(const NumericVector< Number > &udotdot)
Set transient term used by residual and Jacobian evaluation.
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
A kernel for hybridized finite element formulations.
Definition: HDGKernel.h:17
void reinitIncrementAtNodeForDampers(THREAD_ID tid, const std::set< MooseVariable *> &damped_vars)
Compute the incremental change in variables at nodes for dampers.
void overwriteNodeFace(NumericVector< Number > &soln)
Called from explicit time stepping to overwrite boundary positions (explicit dynamics).
Base class for deriving general dampers.
Definition: GeneralDamper.h:21
bool _use_pre_smo_residual
Whether to use the pre-SMO initial residual in the relative convergence check.
MoosePreconditioner const * getPreconditioner() const
virtual const char * what() const
Get out the error message.
std::vector< std::pair< MooseVariableFEBase *, MooseVariableFEBase * > > & couplingEntries(const THREAD_ID tid, const unsigned int nl_sys_num)
void findImplicitGeometricCouplingEntries(GeometricSearchData &geom_search_data, std::unordered_map< dof_id_type, std::vector< dof_id_type >> &graph)
Finds the implicit sparsity graph between geometrically related dofs.
void setupDampers()
Setup damping stuff (called before we actually start)
Real _initial_residual
The initial (i.e., 0th nonlinear iteration) residual, see setPreSMOResidual for a detailed explanatio...
unsigned int n_threads()
std::vector< bool > _variable_autoscaled
Container to hold flag if variable is to participate in autoscaling.
void zeroVectorForResidual(const std::string &vector_name)
virtual void cacheResidualNeighbor(const THREAD_ID tid) override
bool identifyVariableGroupsInNL() const
Whether to identify variable groups in nonlinear systems.
void zeroTaggedVectors(const std::set< TagID > &tags)
Zero all vectors for given tags.
Definition: SystemBase.C:693
const std::set< SubdomainID > & interiorLowerDBlocks() const
Definition: MooseMesh.h:1403
Base class for split-based preconditioners.
Definition: Split.h:25
bool hasActiveBlockObjects(THREAD_ID tid=0) const
std::shared_ptr< DisplacedProblem > displaced_problem
bool hasVector(const std::string &tag_name) const
Check if the named vector exists in the system.
Definition: SystemBase.C:916
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...
unsigned int n_comp(const unsigned int s, const unsigned int var) const
void applyScalingFactors(const std::vector< Real > &inverse_scaling_factors)
Applies scaling factors to the system&#39;s variables.
Definition: SystemBase.C:1487
void computeNodalBCsResidualAndJacobian()
compute the residual and Jacobian for nodal boundary conditions
bool _debugging_residuals
true if debugging residuals
SCALAR
BoundaryID _secondary_boundary
NumericVector< Number > * _Re_non_time
residual vector for non-time contributions
unsigned int TagID
Definition: MooseTypes.h:210
Real computeDamping(const NumericVector< Number > &solution, const NumericVector< Number > &update)
Compute damping.
virtual void reinitNode(const Node *node, const THREAD_ID tid) override
virtual void setPreviousNewtonSolution(const NumericVector< Number > &soln)
virtual void predictorCleanup(NumericVector< libMesh::Number > &ghosted_solution)
Perform cleanup tasks after application of predictor to solution vector.
bool _assemble_constraints_separately
Whether or not to assemble the residual and Jacobian after the application of each constraint...
virtual Elem * elemPtr(const dof_id_type i)
Definition: MooseMesh.C:3113
auto exp(const T &)
TagID systemMatrixTag() const override
Return the Matrix Tag ID for System.
MPI_Info info
NumericVector< Number > & solution()
Definition: SystemBase.h:196
MooseObjectTagWarehouse< DGKernelBase > _dg_kernels
virtual bool haveFV() const override
returns true if this problem includes/needs finite volume functionality.
char ** blocks
face_info_iterator ownedFaceInfoBegin()
Iterators to owned faceInfo objects.
Definition: MooseMesh.C:1510
PARALLEL
void reinitIncrementAtQpsForDampers(THREAD_ID tid, const std::set< MooseVariable *> &damped_vars)
Compute the incremental change in variables at QPs for dampers.
void computeResidualAndJacobianInternal(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags)
Compute residual and Jacobian from contributions not related to constraints, such as nodal boundary c...
void addImplicitGeometricCouplingEntriesToJacobian(bool add=true)
If called with true this will add entries into the jacobian to link together degrees of freedom that ...
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
bool areCoupled(const unsigned int ivar, const unsigned int jvar, const unsigned int nl_sys_num) const
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:333
unsigned int number() const
Get variable number coming from libMesh.
virtual void initialSetup() override
Setup Functions.
Data structure used to hold penetration information.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
const std::vector< std::shared_ptr< NodalConstraint > > & getActiveNodalConstraints() const
Access methods for active objects.
NumericVector< Number > * _u_dot_old
old solution vector for u^dot
Definition: SystemBase.h:1011
bool _has_nodalbc_diag_save_in
If there is a nodal BC having diag_save_in.
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
Base class for automatic differentiation Dirichlet BCs.
void add(std::shared_ptr< MooseObject > obj)
add adds a new object to the warehouse and stores attributes/metadata about it for running queries/fi...
Definition: TheWarehouse.C:116
virtual void getDiracElements(std::set< const Elem *> &elems) override
Fills "elems" with the elements that should be looped over for Dirac Kernels.
void setupDM()
Setup the PETSc DM object (when appropriate)
void setCurrentlyComputingResidual(bool currently_computing_residual) final
Set whether or not the problem is in the process of computing the residual.
void checkKernelCoverage(const std::set< SubdomainID > &mesh_subdomains) const
void addDGKernel(std::string dg_kernel_name, const std::string &name, InputParameters &parameters)
Adds a DG kernel.
void computeJacobian(libMesh::SparseMatrix< Number > &jacobian, const std::set< TagID > &tags)
Associate jacobian to systemMatrixTag, and then form a matrix for all the tags.
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseBase.h:127
char ** vars
virtual void reinitNeighborPhys(const Elem *neighbor, unsigned int neighbor_side, const std::vector< Point > &physical_points, const THREAD_ID tid) override
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition: SubProblem.C:92
std::vector< T * > & queryInto(std::vector< T *> &results, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Definition: TheWarehouse.h:311
void getNodeDofs(dof_id_type node_id, std::vector< dof_id_type > &dofs)
Base class for all Constraint types.
Definition: Constraint.h:19
std::set< TagID > _nl_vector_tags
Vector tags to temporarily store all tags associated with the current system.
std::vector< std::string > _ignore_variables_for_autoscaling
A container for variables that do not partipate in autoscaling.
void residualSetup() override
Base boundary condition of a Dirichlet type.
virtual void associateVectorToTag(NumericVector< Number > &vec, TagID tag)
Associate a vector for a given tag.
Definition: SystemBase.C:973
virtual void reinitNodes(const std::vector< dof_id_type > &nodes, const THREAD_ID tid) override
MooseObjectTagWarehouse< NodalBCBase > _nodal_bcs
virtual void addJacobianOffDiagScalar(unsigned int ivar, const THREAD_ID tid=0)
virtual void setException(const std::string &message)
Set an exception, which is stored at this point by toggling a member variable in this class...
const std::vector< std::shared_ptr< NodeFaceConstraint > > & getActiveNodeFaceConstraints(BoundaryID boundary_id, bool displaced) const
virtual void customSetup(const ExecFlagType &exec_type, THREAD_ID tid=0) const
bool needSubdomainMaterialOnSide(SubdomainID subdomain_id, THREAD_ID tid) const
Indicates whether this system needs material properties on internal sides.
Factory & _factory
Definition: SystemBase.h:989
MooseObjectWarehouse< T > & getVectorTagsObjectWarehouse(const std::set< TagID > &tags, THREAD_ID tid)
Retrieve a moose object warehouse in which every moose object at least has one of the given vector ta...
virtual const Node * queryNodePtr(const dof_id_type i) const
Definition: MooseMesh.C:860
const ElementPairInfo & getElemPairInfo(std::pair< const Elem *, const Elem *> elem_pair) const
MooseObjectWarehouseBase< Split > _splits
Decomposition splits.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
NumericVector< Number > * _u_dotdot
solution vector for u^dotdot
Definition: SystemBase.h:1008
bool hasActiveMortarConstraints(const std::pair< BoundaryID, BoundaryID > &mortar_interface_key, bool displaced) const
const Parallel::Communicator & comm() const
NumericVector< Number > & add_vector(std::string_view vec_name, const bool projections=true, const ParallelType type=PARALLEL)
Solving a linear problem.
Definition: MooseTypes.h:849
bool _has_nodalbc_save_in
If there is a nodal BC having save_in.
bool hasActiveNodalConstraints() const
Deterimine if active objects exist.
virtual bool hasMatrix(TagID tag) const
Check if the tagged matrix exists in the system.
Definition: SystemBase.h:360
MooseObjectWarehouse< NodalDamper > _nodal_dampers
Nodal Dampers for each thread.
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver()=0
dof_id_type n_dofs(const unsigned int vn) const
Real preSMOResidual() const
The pre-SMO residual.
std::unique_ptr< libMesh::DiagonalMatrix< Number > > _scaling_matrix
A diagonal matrix used for computing scaling.
virtual void setSolutionUDotOld(const NumericVector< Number > &u_dot_old)
virtual void associateMatrixToTag(libMesh::SparseMatrix< Number > &matrix, TagID tag)
Associate a matrix to a tag.
Definition: SystemBase.C:1068
bool hasDiagSaveIn() const
Weather or not the nonlinear system has diagonal Jacobian save-ins.
This class provides an interface for common operations on field variables of both FE and FV types wit...
const Parallel::Communicator & _communicator
void updateActive(THREAD_ID tid=0) override
Update the various active lists.
Real initialResidual() const
The initial residual.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
bool needInterfaceMaterialOnSide(BoundaryID bnd_id, THREAD_ID tid) const
Indicated whether this system needs material properties on interfaces.
const libMesh::ConstElemRange & getCurrentAlgebraicElementRange()
These are the element and nodes that contribute to the jacobian and residual for this local processor...
std::size_t _num_scaling_groups
The number of scaling groups.
const libMesh::ConstNodeRange & getCurrentAlgebraicNodeRange()
void computingScalingJacobian(bool computing_scaling_jacobian)
Setter for whether we&#39;re computing the scaling jacobian.
dof_id_type n_local_dofs(const unsigned int vn) const
virtual void updateActive(THREAD_ID tid=0) override
Update the active status of Kernels.
bool has_dofs(const unsigned int s=libMesh::invalid_uint) const
std::map< dof_id_type, PenetrationInfo * > & _penetration_info
Data structure of nodes and their associated penetration information.
bool hasActiveNodeElemConstraints(SubdomainID secondary_id, SubdomainID primary_id, bool displaced) const
Real _pre_smo_residual
The pre-SMO residual, see setPreSMOResidual for a detailed explanation.
bool hasDampers()
Whether or not this system has dampers.
const std::vector< std::shared_ptr< NodeElemConstraintBase > > & getActiveNodeElemConstraints(SubdomainID secondary_id, SubdomainID primary_id, bool displaced) const
bool _compute_scaling_once
Whether the scaling factors should only be computed once at the beginning of the simulation through a...
void computeResidualTags(const std::set< TagID > &tags)
Form multiple tag-associated residual vectors for all the given tags.
virtual void cacheJacobianNeighbor(const THREAD_ID tid) override
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
bool _has_save_in
If there is any Kernel or IntegratedBC having save_in.
virtual const Node & nodeRef(const dof_id_type i) const
Definition: MooseMesh.C:834
TagID _Ke_system_tag
Tag for system contribution Jacobian.
virtual void setResidual(NumericVector< libMesh::Number > &residual, const THREAD_ID tid) override
dof_id_type n_dofs() const
virtual void disassociateMatrixFromTag(libMesh::SparseMatrix< Number > &matrix, TagID tag)
Disassociate a matrix from a tag.
Definition: SystemBase.C:1080
Scope guard for starting and stopping Floating Point Exception Trapping.
virtual void zero()=0
auto max(const L &left, const R &right)
Serves as a base class for DGKernel and ADDGKernel.
Definition: DGKernelBase.h:32
const Variable & variable(const unsigned int c) const override
void constraintResiduals(NumericVector< Number > &residual, bool displaced)
Add residual contributions from Constraints.
Base class for MOOSE preconditioners.
NumericVector< Number > & addVector(const std::string &vector_name, const bool project, const libMesh::ParallelType type)
Adds a solution length vector to the system.
virtual GeometricSearchData & geomSearchData() override
std::unordered_map< std::pair< BoundaryID, BoundaryID >, ComputeMortarFunctor > _undisplaced_mortar_functors
Functors for computing undisplaced mortar constraints.
Specialization for filling multiple "small" preconditioning matrices simulatenously.
virtual bool matrixFromColoring() const
Whether a system matrix is formed from coloring.
Definition: SolverSystem.h:102
void update()
Update the system (doing libMesh magic)
Definition: SystemBase.C:1235
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num) override
void addScalarKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds a scalar kernel.
void addBoundaryCondition(const std::string &bc_name, const std::string &name, InputParameters &parameters)
Adds a boundary condition.
bool hasActiveNodeFaceConstraints(BoundaryID boundary_id, bool displaced) const
void computeResidual(NumericVector< Number > &residual, TagID tag_id)
Form a residual vector for a given tag.
virtual void addCachedResidualDirectly(NumericVector< libMesh::Number > &residual, const THREAD_ID tid)
Allows for all the residual contributions that are currently cached to be added directly into the vec...
virtual unsigned int nVariables() const
Get the number of variables in this system.
Definition: SystemBase.C:883
EXTERN_C_BEGIN PetscErrorCode DMCreate_Moose(DM)
bool hasActiveBoundaryObjects(THREAD_ID tid=0) const
bool _need_residual_ghosted
Whether or not a ghosted copy of the residual needs to be made.
virtual void activateAllMatrixTags()
Make all existing matrices active.
Definition: SystemBase.C:1123
virtual const std::string & name() const
Definition: SystemBase.C:1332
virtual void jacobianSetup()
Definition: SystemBase.C:1598
virtual bool containsTimeKernel() override
If the system has a kernel that corresponds to a time derivative.
void onTimestepBegin()
Called at the beginning of the time step.
const ConstBndNodeRange & getCurrentAlgebraicBndNodeRange()
std::vector< dof_id_type, Threads::scalable_allocator< dof_id_type > > Row
MooseObjectTagWarehouse< DiracKernelBase > _dirac_kernels
Dirac Kernel storage for each thread.
void closeTaggedMatrices(const std::set< TagID > &tags)
Close all matrices associated the tags.
Definition: SystemBase.C:1052
TagID _Re_non_time_tag
Tag for non-time contribution residual.
std::set< TagID > _nl_matrix_tags
Matrix tags to temporarily store all tags associated with the current system.
void solutionInvalidAccumulation()
Pass the number of solution invalid occurrences from current iteration to cumulative counters...
void set_basic_system_only()
std::map< std::pair< BoundaryID, BoundaryID >, NearestNodeLocator * > _nearest_node_locators
void setPredictor(std::shared_ptr< Predictor > predictor)
Real _resid_vs_jac_scaling_param
The param that indicates the weighting of the residual vs the Jacobian in determining variable scalin...
bool _auto_scaling_initd
Whether we&#39;ve initialized the automatic scaling data structures.
virtual void computeScalingResidual()=0
Compute a "residual" for automatic scaling purposes.
bool _doing_dg
true if DG is active (optimization reasons)
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
Definition: SystemBase.C:1155
void syncIteration()
Sync iteration counts to main processor.
virtual void deactivateAllMatrixTags()
Make matrices inactive.
Definition: SystemBase.C:1111
unsigned int number() const
void computeResidualAndJacobianTags(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags)
Form possibly multiple tag-associated vectors and matrices.
SERIAL
bool needBoundaryMaterialOnSide(BoundaryID bnd_id, THREAD_ID tid) const
Indicated whether this system needs material properties on boundaries.
MooseObjectWarehouse< DirichletBCBase > _preset_nodal_bcs
std::unordered_map< unsigned int, unsigned int > _var_to_group_var
A map from variable index to group variable index and it&#39;s associated (inverse) scaling factor...
const std::vector< std::shared_ptr< T > > & getActiveObjects(THREAD_ID tid=0) const
Retrieve complete vector to the active all/block/boundary restricted objects for a given thread...
std::vector< unsigned int > _current_l_its
virtual void zero()=0
virtual std::unique_ptr< Base > create()=0
void setCurrentNonlinearSystem(const unsigned int nl_sys_num)
std::shared_ptr< T > getActiveObject(const std::string &name, THREAD_ID tid=0) const
This is the common base class for the three main kernel types implemented in MOOSE, Kernel, VectorKernel and ArrayKernel.
Definition: KernelBase.h:23
dof_id_type id() const
std::vector< dof_id_type > _secondary_nodes
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3448
void min(const T &r, T &o, Request &req) const
void computeDiracContributions(const std::set< TagID > &tags, bool is_jacobian)
void updateActive(THREAD_ID tid)
Update active objects of Warehouses owned by NonlinearSystemBase.
TheWarehouse & theWarehouse() const
unsigned int n_vars
void reinitMaterialsNeighbor(SubdomainID blk_id, const THREAD_ID tid, bool swap_stateful=true, const std::deque< MaterialBase *> *reinit_mats=nullptr)
reinit materials on the neighboring element face
const ElementPairList & getElemPairs() const
FieldSplitPreconditionerBase & getFieldSplitPreconditioner()
std::unordered_map< std::pair< BoundaryID, BoundaryID >, ComputeMortarFunctor > _displaced_mortar_functors
Functors for computing displaced mortar constraints.
GHOSTED
boundary_id_type BoundaryID
Real referenceResidual() const
The reference residual used in relative convergence check.
void addSplit(const std::string &split_name, const std::string &name, InputParameters &parameters)
Adds a split.
bool _automatic_scaling
Whether to automatically scale the variables.
Definition: SystemBase.h:1055
void computeJacobianTags(const std::set< TagID > &tags)
Computes multiple (tag associated) Jacobian matricese.
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition: MooseApp.h:172
std::shared_ptr< MoosePreconditioner > _preconditioner
Preconditioner.
virtual void timestepSetup(THREAD_ID tid=0) const
NonlinearSystemBase & currentNonlinearSystem()
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
void computingScalingResidual(bool computing_scaling_residual)
Setter for whether we&#39;re computing the scaling residual.
virtual void setupDM()=0
setup the data management data structure that manages the field split
SubProblem & subproblem()
Definition: SystemBase.h:101
std::vector< std::string > _vecs_to_zero_for_residual
vectors that will be zeroed before a residual computation
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Definition: SubProblem.C:311
std::shared_ptr< Split > getSplit(const std::string &name)
Retrieves a split by name.
std::unique_ptr< NumericVector< Number > > solution
SubProblem & _subproblem
The subproblem for whom this class holds variable data, etc; this can either be the governing finite ...
Definition: SystemBase.h:983
void subdomainsCovered(std::set< SubdomainID > &subdomains_covered, std::set< std::string > &unique_variables, THREAD_ID tid=0) const
Populates a set of covered subdomains and the associated variable names.
void addImplicitGeometricCouplingEntries(GeometricSearchData &geom_search_data)
Adds entries to the Jacobian in the correct positions for couplings coming from dofs being coupled th...
virtual void addHDGKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds a hybridized discontinuous Galerkin (HDG) kernel.
virtual void zero_rows(std::vector< numeric_index_type > &rows, T diag_value=0.0)
MooseObjectTagWarehouse< KernelBase > _kernels
MooseObjectWarehouse< T > & getMatrixTagObjectWarehouse(TagID tag_id, THREAD_ID tid)
Retrieve a moose object warehouse in which every moose object has the given matrix tag...
bool shouldEvaluatePreSMOResidual() const
We offer the option to check convergence against the pre-SMO residual.
std::vector< VectorTag > getVectorTags(const std::set< TagID > &tag_ids) const
Definition: SubProblem.C:172
Moose::SolveType _type
Definition: SolverParams.h:19
Base class for deriving nodal dampers.
Definition: NodalDamper.h:27
virtual void disassociateVectorFromTag(NumericVector< Number > &vec, TagID tag)
Disassociate a given vector from a given tag.
virtual void cacheResidual(const THREAD_ID tid) override
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:384
virtual void computeScalingJacobian()=0
Compute a "Jacobian" for automatic scaling purposes.
bool errorOnJacobianNonzeroReallocation() const
Will return True if the user wants to get an error when a nonzero is reallocated in the Jacobian by P...
This is the ElementPairLocator class.
This is the ElementPairInfo class.
std::map< BoundaryID, std::shared_ptr< ElementPairLocator > > _element_pair_locators
Moose::CouplingType coupling() const
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1149
void setupScalingData()
Setup group scaling containers.
virtual GeometricSearchData & geomSearchData()=0
const bool & usePreSMOResidual() const
Whether we are using pre-SMO residual in relative convergence checks.
MooseObjectTagWarehouse< HDGKernel > _hybridized_kernels
const std::set< SubdomainID > & boundaryLowerDBlocks() const
Definition: MooseMesh.h:1407
std::vector< SubdomainName > getSubdomainNames(const std::vector< SubdomainID > &subdomain_ids) const
Get the associated subdomainNames for the subdomain ids that are passed in.
Definition: MooseMesh.C:1769
auto log(const T &)
AuxiliarySystem & getAuxiliarySystem()
virtual void initialSetup(THREAD_ID tid=0) const
Convenience methods for calling object setup methods.
virtual void updateGeomSearch(GeometricSearchData::GeometricSearchType type=GeometricSearchData::ALL) override
void closeTaggedVectors(const std::set< TagID > &tags)
Close all vectors for given tags.
Definition: SystemBase.C:667
Base class for deriving any boundary condition that works at nodes.
Definition: NodalBCBase.h:26
void computeResidualInternal(const std::set< TagID > &tags)
Compute the residual for a given tag.
virtual void prepareAssembly(const THREAD_ID tid) override
bool computeScaling()
Method used to obtain scaling factors for variables.
Interface for objects interacting with the PerfGraph.
virtual std::map< TagName, TagID > & getMatrixTags()
Return all matrix tags in the system, where a tag is represented by a map from name to ID...
Definition: SubProblem.h:253
virtual bool hasVariable(const std::string &var_name) const
Query a system for a variable.
Definition: SystemBase.C:843
virtual void setCurrentSubdomainID(const Elem *elem, const THREAD_ID tid) override
virtual void clearDiracInfo() override
Gets called before Dirac Kernels are asked to add the points they are supposed to be evaluated in...
void destroyColoring()
Destroy the coloring object if it exists.
virtual void reinitNodesNeighbor(const std::vector< dof_id_type > &nodes, const THREAD_ID tid) override
bool identify_variable_groups() const
virtual void close()=0
virtual void jacobianSetup(THREAD_ID tid=0) const
ConstraintWarehouse _constraints
Constraints storage object.
virtual void turnOffJacobian()
Turn off the Jacobian (must be called before equation system initialization)
TagID residualVectorTag() const override
const std::map< BoundaryID, std::vector< std::shared_ptr< T > > > & getActiveBoundaryObjects(THREAD_ID tid=0) const
void computingNonlinearResid(bool computing_nonlinear_residual) final
Set whether or not the problem is in the process of computing the nonlinear residual.
virtual void customSetup(const ExecFlagType &exec_type) override
ComputeType
The type of nonlinear computation being performed.
Definition: MooseTypes.h:781
Base class for deriving element dampers.
Definition: ElementDamper.h:33
Base interface for field split preconditioner.
bool _add_implicit_geometric_coupling_entries_to_jacobian
Whether or not to add implicit geometric couplings to the Jacobian for FDP.
const_iterator end() const
virtual void addNodalKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds a NodalKernel.
virtual unsigned int numMatrixTags() const
The total number of tags.
Definition: SubProblem.h:248
Base class for creating new types of boundary conditions.
tbb::split split
MooseApp & _app
Definition: SystemBase.h:988
FEProblemBase & _fe_problem
the governing finite element/volume problem
Definition: SystemBase.h:986
virtual void reinitElemPhys(const Elem *elem, const std::vector< Point > &phys_points_in_elem, const THREAD_ID tid)=0
virtual MooseVariableScalar & getScalarVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a scalar variable with specified number.
Definition: SystemBase.C:145
ParallelType type() const
virtual NumericVector< Number > & RHS()=0
std::vector< VariableWarehouse > _vars
Variable warehouses (one for each thread)
Definition: SystemBase.h:996
Provides a way for users to bail out of the current solve.
unsigned int _n_residual_evaluations
Total number of residual evaluations that have been performed.
virtual void update()
void addDiracKernel(const std::string &kernel_name, const std::string &name, InputParameters &parameters)
Adds a Dirac kernel.
virtual void close()=0
void computeJacobianInternal(const std::set< TagID > &tags)
Form multiple matrices for all the tags.
bool _has_diag_save_in
If there is any Kernel or IntegratedBC having diag_save_in.
Base class for creating new types of nodal kernels.
const FEType & variable_type(const unsigned int i) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
std::unique_ptr< NumericVector< Number > > _residual_copy
Copy of the residual vector, or nullptr if a copy is not needed.
virtual void subdomainSetup()
Definition: SystemBase.C:1584
bool hasSaveIn() const
Weather or not the nonlinear system has save-ins.
Generic class for solving transient nonlinear problems.
Definition: SubProblem.h:78
TagID timeVectorTag() const override
Ideally, we should not need this API.
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:18
MooseMesh & _mesh
Definition: SystemBase.h:991
virtual std::vector< std::string > timeKernelVariableNames() override
Returns the names of the variables that have time derivative kernels in the system.
bool hasActiveObjects(THREAD_ID tid=0) const
NonlinearSystemBase(FEProblemBase &problem, libMesh::System &sys, const std::string &name)
void max(const T &r, T &o, Request &req) const
NumericVector< Number > * _u_dot
solution vector for u^dot
Definition: SystemBase.h:1006
MooseObjectWarehouse< ElementDamper > _element_dampers
Element Dampers for each thread.
void addObject(std::shared_ptr< Constraint > object, THREAD_ID tid=0, bool recurse=true) override
Add Constraint object to the warehouse.
virtual void setSolutionUDot(const NumericVector< Number > &udot)
Set transient term used by residual and Jacobian evaluation.
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:1016
virtual void augmentSparsity(libMesh::SparsityPattern::Graph &sparsity, std::vector< dof_id_type > &n_nz, std::vector< dof_id_type > &n_oz) override
Will modify the sparsity pattern to add logical geometric connections.
const std::vector< std::shared_ptr< MortarConstraintBase > > & getActiveMortarConstraints(const std::pair< BoundaryID, BoundaryID > &mortar_interface_key, bool displaced) const
MooseObjectWarehouse< T > & getMatrixTagsObjectWarehouse(const std::set< TagID > &tags, THREAD_ID tid)
Retrieve a moose object warehouse in which every moose object has one of the given matrix tags...
void computeScalarKernelsJacobians(const std::set< TagID > &tags)
void setInitialResidual(Real r)
Record the initial residual (for later relative convergence check)
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse...
Definition: TheWarehouse.h:466
virtual Assembly & assembly(const THREAD_ID tid, const unsigned int sys_num)=0
const_iterator begin() const
Base class for deriving dampers.
Definition: Damper.h:24
bool getFailNextNonlinearConvergenceCheck() const
Whether it will skip further residual evaluations and fail the next nonlinear convergence check(s) ...
Base class shared by AD and non-AD scalar kernels.
void addDamper(const std::string &damper_name, const std::string &name, InputParameters &parameters)
Adds a damper.
IntRange< T > make_range(T beg, T end)
virtual MooseMesh & mesh() override
virtual void postAddResidualObject(ResidualObject &)
Called after any ResidualObject-derived objects are added to the system.
const std::vector< VariableName > & getVariableNames() const
Definition: SystemBase.h:860
virtual void preInit() override
This is called prior to the libMesh system has been init&#39;d.
Definition: SolverSystem.C:32
virtual void updateActive(THREAD_ID tid=0) override
Update the active status of Kernels.
virtual void timestepSetup() override
bool hasActiveElemElemConstraints(const InterfaceID interface_id, bool displaced) const
bool _off_diagonals_in_auto_scaling
Whether to include off diagonals when determining automatic scaling factors.
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:195
void reinitNodeFace(const Node &secondary_node, const BoundaryID secondary_boundary, const PenetrationInfo &info, const bool displaced)
Reinitialize quantities such as variables, residuals, Jacobians, materials for node-face constraints...
Base class for deriving any boundary condition of a integrated type.
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
NumericVector< Number > * _residual_ghosted
ghosted form of the residual
void setCachedJacobian(GlobalDataKey)
Sets previously-cached Jacobian values via SparseMatrix::set() calls.
Definition: Assembly.C:4492
TagID _Re_tag
Used for the residual vector from PETSc.
virtual void customSetup(const ExecFlagType &exec_type)
Definition: SystemBase.C:1577
MooseObjectWarehouse< T > & getVectorTagObjectWarehouse(TagID tag_id, THREAD_ID tid)
Retrieve a moose object warehouse in which every moose object has the given vector tag...
void computeNodalBCs(NumericVector< Number > &residual)
Enforces nodal boundary conditions.
const std::set< SubdomainID > & getSubdomainsForVar(unsigned int var_number) const
Definition: SystemBase.h:761
virtual void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true)
Adds an object to the storage structure.
bool ignoreZerosInJacobian() const
Will return true if zeros in the Jacobian are to be dropped from the sparsity pattern.
const ExecFlagType EXEC_PRE_KERNELS
Definition: Moose.C:56
libMesh::System & _sys
void mortarConstraints(Moose::ComputeType compute_type, const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags)
Do mortar constraint residual/jacobian computations.
NumericVector< Number > * _increment_vec
increment vector
InterfaceKernelBase is the base class for all InterfaceKernel type classes.
QueryCache & condition(Args &&... args)
Adds a new condition to the query.
Definition: TheWarehouse.h:284
bool doingDG() const
Getter for _doing_dg.
void computeResidualTag(NumericVector< Number > &residual, TagID tag_id)
Computes residual for a given tag.
void addConstraint(const std::string &c_name, const std::string &name, InputParameters &parameters)
Adds a Constraint.
virtual TagName vectorTagName(const TagID tag) const
Retrieve the name associated with a TagID.
Definition: SubProblem.C:221
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
bool restoreOriginalNonzeroPattern() const
face_info_iterator ownedFaceInfoEnd()
Definition: MooseMesh.C:1519
void constraintJacobians(const SparseMatrix< Number > &jacobian_to_view, bool displaced)
Add jacobian contributions from Constraints.
virtual libMesh::System & system() override
Get the reference to the libMesh system.
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:90
std::vector< BoundaryID > getBoundaryIDs(const Elem *const elem, const unsigned short int side) const
Returns a vector of boundary IDs for the requested element on the requested side. ...
bool preSolve()
Perform some steps to get ready for the solver.
const std::unordered_map< std::pair< BoundaryID, BoundaryID >, AutomaticMortarGeneration > & getMortarInterfaces(bool on_displaced) const
bool _has_constraints
Whether or not this system has any Constraints.
dof_id_type first_dof(const processor_id_type proc) const
bool _computed_scaling
Flag used to indicate whether we have already computed the scaling Jacobian.
void remove_algebraic_ghosting_functor(GhostingFunctor &evaluable_functor)
MooseObjectTagWarehouse< InterfaceKernelBase > _interface_kernels
unsigned int n_vars() const
void resetSolutionInvalidCurrentIteration()
Reset the number of solution invalid occurrences back to zero.
NumericVector< Number > & residualVector(TagID tag)
Return a residual vector that is associated with the residual tag.
NumericVector< Number > & solutionOld()
Definition: SystemBase.h:197
NumericVector< Number > & getResidualNonTimeVector()
Return a numeric vector that is associated with the nontime tag.
virtual bool hasScalarVariable(const std::string &var_name) const
Definition: SystemBase.C:868
const TagName PREVIOUS_NL_SOLUTION_TAG
Definition: MooseTypes.C:28
processor_id_type processor_id() const
std::shared_ptr< Predictor > _predictor
If predictor is active, this is non-NULL.
void enforceNodalConstraintsResidual(NumericVector< Number > &residual)
Enforce nodal constraints.
void subdomainsCovered(std::set< SubdomainID > &subdomains_covered, std::set< std::string > &unique_variables, THREAD_ID tid=0) const
Update supplied subdomain and variable coverate containters.
MooseObjectWarehouse< GeneralDamper > _general_dampers
General Dampers.
const std::vector< std::shared_ptr< ElemElemConstraint > > & getActiveElemElemConstraints(InterfaceID interface_id, bool displaced) const
virtual void initialSetup()
Setup Functions.
Definition: SystemBase.C:1550
bool defaultGhosting()
Whether or not the user has requested default ghosting ot be on.
Definition: SubProblem.h:144
void addCachedJacobian(GlobalDataKey)
Adds the values that have been cached by calling cacheJacobian() and or cacheJacobianNeighbor() to th...
Definition: Assembly.C:3815
virtual void cacheJacobian(const THREAD_ID tid) override
auto min(const L &left, const R &right)
void jacobianSetup() override
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition: SystemBase.C:925
MooseObjectTagWarehouse< IntegratedBCBase > _integrated_bcs
const DofMap & get_dof_map() const
virtual void reinitNodeFace(const Node *node, BoundaryID bnd_id, const THREAD_ID tid) override
virtual void residualSetup()
Definition: SystemBase.C:1591
virtual void reinitOffDiagScalars(const THREAD_ID tid) override
processor_id_type processor_id() const
virtual void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true) override
Adds an object to the storage structure.
virtual void setNeighborSubdomainID(const Elem *elem, unsigned int side, const THREAD_ID tid) override
virtual void addResidualScalar(const THREAD_ID tid=0)
virtual void subdomainSetup(THREAD_ID tid=0) const
virtual void jacobianSetup() override
virtual void addCachedResidual(const THREAD_ID tid) override
std::vector< std::vector< std::string > > _scaling_group_variables
A container of variable groupings that can be used in scaling calculations.
void addInterfaceKernel(std::string interface_kernel_name, const std::string &name, InputParameters &parameters)
Adds an interface kernel.
FieldSplitPreconditionerBase * _fsp
The field split preconditioner if this sytem is using one.
auto index_range(const T &sizable)
virtual NumericVector< Number > & residualCopy() override
void reinitMortarFunctors()
Update the mortar functors if the mesh has changed.
virtual NumericVector< Number > & residualGhosted() override
DiracKernelBase is the base class for all DiracKernel type classes.
void assembleScalingVector()
Assemble the numeric vector of scaling factors such that it can be used during assembly of the system...
BoundaryID _primary_boundary
NumericVector< Number > * _u_dotdot_old
old solution vector for u^dotdot
Definition: SystemBase.h:1013
Base variable class.
MooseObjectTagWarehouse< ScalarKernelBase > _scalar_kernels
virtual void residualEnd(THREAD_ID tid=0) const
void setConstraintSecondaryValues(NumericVector< Number > &solution, bool displaced)
Sets the value of constrained variables in the solution vector.
unsigned int THREAD_ID
Definition: MooseTypes.h:209
uint8_t dof_id_type
virtual void addJacobianScalar(const THREAD_ID tid=0)
NearestNodeLocator & _nearest_node
const std::map< dof_id_type, std::vector< dof_id_type > > & nodeToElemMap()
If not already created, creates a map from every node to all elements to which they are connected...
Definition: MooseMesh.C:1178
const std::set< SubdomainID > & meshSubdomains() const
Returns a read-only reference to the set of subdomains currently present in the Mesh.
Definition: MooseMesh.C:3171
ParallelType
virtual void addCachedJacobian(const THREAD_ID tid) override
virtual void timestepSetup()
Definition: SystemBase.C:1570
virtual ~NonlinearSystemBase()
virtual void preInit() override
This is called prior to the libMesh system has been init&#39;d.
virtual void residualSetup() override
void setPreconditioner(std::shared_ptr< MoosePreconditioner > pc)
Sets a preconditioner.
virtual void localize(std::vector< T > &v_local) const=0
MooseObjectWarehouse< ADDirichletBCBase > _ad_preset_nodal_bcs
virtual libMesh::System & system() override
Get the reference to the libMesh system.
Key structure for APIs manipulating global vectors/matrices.
Definition: Assembly.h:805