https://mooseframework.inl.gov
LinearSystem.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 "LinearSystem.h"
11 #include "AuxiliarySystem.h"
12 #include "Problem.h"
13 #include "FEProblem.h"
14 #include "PetscSupport.h"
15 #include "Factory.h"
16 #include "ParallelUniqueId.h"
19 #include "DisplacedProblem.h"
20 #include "Parser.h"
21 #include "MooseMesh.h"
22 #include "MooseUtils.h"
23 #include "MooseApp.h"
24 #include "TimeIntegrator.h"
25 #include "Assembly.h"
27 #include "Moose.h"
28 #include "ConsoleStream.h"
29 #include "MooseError.h"
31 #include "LinearFVFluxKernel.h"
32 #include "UserObject.h"
33 #include "SolutionInvalidity.h"
34 #include "MooseLinearVariableFV.h"
35 #include "LinearFVTimeDerivative.h"
36 #include "LinearFVFluxKernel.h"
39 #include "GradientLimiterType.h"
40 
41 // libMesh
42 #include "libmesh/linear_solver.h"
43 #include "libmesh/quadrature_gauss.h"
44 #include "libmesh/dense_vector.h"
45 #include "libmesh/boundary_info.h"
46 #include "libmesh/petsc_matrix.h"
47 #include "libmesh/petsc_vector.h"
48 #include "libmesh/petsc_nonlinear_solver.h"
49 #include "libmesh/numeric_vector.h"
50 #include "libmesh/mesh.h"
51 #include "libmesh/dense_subvector.h"
52 #include "libmesh/dense_submatrix.h"
53 #include "libmesh/dof_map.h"
54 #include "libmesh/sparse_matrix.h"
55 #include "libmesh/petsc_matrix.h"
56 #include "libmesh/default_coupling.h"
57 #include "libmesh/diagonal_matrix.h"
58 #include "libmesh/petsc_solver_exception.h"
59 
60 #include <ios>
61 
62 using namespace libMesh;
63 
64 namespace Moose
65 {
66 void
67 compute_linear_system(libMesh::EquationSystems & es, const std::string & system_name)
68 {
69  FEProblemBase * p = es.parameters.get<FEProblemBase *>("_fe_problem_base");
70  auto & sys = p->getLinearSystem(p->linearSysNum(system_name));
71  auto & lin_sys = sys.linearImplicitSystem();
72  auto & matrix = *(sys.linearImplicitSystem().matrix);
73  auto & rhs = *(sys.linearImplicitSystem().rhs);
74  p->computeLinearSystemSys(lin_sys, matrix, rhs);
75 }
76 }
77 
78 LinearSystem::LinearSystem(FEProblemBase & fe_problem, const std::string & name)
79  : SolverSystem(fe_problem, fe_problem, name, Moose::VAR_SOLVER),
80  PerfGraphInterface(fe_problem.getMooseApp().perfGraph(), "LinearSystem"),
81  LinearFVGradientInterface(static_cast<SystemBase &>(*this)),
82  _sys(fe_problem.es().add_system<LinearImplicitSystem>(name)),
83  _rhs_time_tag(-1),
84  _rhs_time(NULL),
85  _rhs_non_time_tag(-1),
86  _rhs_non_time(NULL),
87  _n_linear_iters(0),
88  _converged(false),
89  _linear_implicit_system(fe_problem.es().get_system<LinearImplicitSystem>(name))
90 {
92  // Don't need to add the matrix - it already exists. Well, technically it will exist
93  // after the initialization. Right now it is just a nullpointer. We will just make sure
94  // we associate the tag with the system matrix for now.
96 
97  // We create a tag for the right hand side, the vector is already in the libmesh system
100 
102 }
103 
104 LinearSystem::~LinearSystem() = default;
105 
106 void
108 {
110 
111 #ifdef MOOSE_KOKKOS_ENABLED
114 #endif
115 }
116 
117 void
119 {
122  // Checking if somebody accidentally assigned nonlinear variables to this system
123  const auto & var_names = _vars[0].names();
124  for (const auto & name : var_names)
125  if (!dynamic_cast<MooseLinearVariableFVReal *>(_vars[0].getVariable(name)))
126  mooseError("You are trying to add a nonlinear variable to a linear system! The variable "
127  "which is assigned to the wrong system: ",
128  name);
129 
131 
132  // Calling initial setup for the linear kernels
133  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
134  {
135  std::vector<LinearFVElementalKernel *> fv_elemental_kernels;
137  .query()
138  .template condition<AttribSysNum>(number())
139  .template condition<AttribSystem>("LinearFVElementalKernel")
140  .template condition<AttribKokkos>(false)
141  .template condition<AttribThread>(tid)
142  .queryInto(fv_elemental_kernels);
143 
144  for (auto * fv_kernel : fv_elemental_kernels)
145  fv_kernel->initialSetup();
146 
147  std::vector<LinearFVFluxKernel *> fv_flux_kernels;
149  .query()
150  .template condition<AttribSysNum>(number())
151  .template condition<AttribSystem>("LinearFVFluxKernel")
152  .template condition<AttribKokkos>(false)
153  .template condition<AttribThread>(tid)
154  .queryInto(fv_flux_kernels);
155 
156  for (auto * fv_kernel : fv_flux_kernels)
157  fv_kernel->initialSetup();
158 
159  std::vector<LinearFVBoundaryCondition *> fv_bcs;
161  .query()
162  .template condition<AttribSysNum>(number())
163  .template condition<AttribSystem>("LinearFVBoundaryCondition")
164  .template condition<AttribKokkos>(false)
165  .template condition<AttribThread>(tid)
166  .queryInto(fv_bcs);
167 
168  for (auto * fv_bc : fv_bcs)
169  fv_bc->initialSetup();
170  }
171 
172 #ifdef MOOSE_KOKKOS_ENABLED
174 #endif
175 }
176 
177 void
179 {
182 }
183 
184 void
185 LinearSystem::computeLinearSystemTags(const std::set<TagID> & vector_tags,
186  const std::set<TagID> & matrix_tags,
187  const bool compute_gradients)
188 {
189  parallel_object_only();
190 
191  TIME_SECTION("LinearSystem::computeLinearSystemTags", 5);
192 
194 
196 
197  try
198  {
199  computeLinearSystemInternal(vector_tags, matrix_tags, compute_gradients);
200  }
201  catch (MooseException & e)
202  {
203  _console << "Exception detected " << e.what() << std::endl;
204  // The buck stops here, we have already handled the exception by
205  // calling stopSolve(), it is now up to PETSc to return a
206  // "diverged" reason during the next solve.
207  }
208 }
209 
210 void
211 LinearSystem::computeLinearSystemInternal(const std::set<TagID> & vector_tags,
212  const std::set<TagID> & matrix_tags,
213  const bool compute_gradients)
214 {
215  TIME_SECTION("computeLinearSystemInternal", 3);
216 
217  // Before we assemble we clear up the matrix and the vector
220 
221  // Make matrix ready to use
223 
224  for (auto tag : matrix_tags)
225  {
226  auto & matrix = getMatrix(tag);
227  // Necessary for speed
228  if (auto petsc_matrix = dynamic_cast<PetscMatrix<Number> *>(&matrix))
229  {
230  LibmeshPetscCall(MatSetOption(petsc_matrix->mat(),
231  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
232  PETSC_TRUE));
234  LibmeshPetscCall(
235  MatSetOption(petsc_matrix->mat(), MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
236  }
237  }
238 
239  if (compute_gradients)
241 
242 #ifdef MOOSE_KOKKOS_ENABLED
243  // Kokkos assembly runs first: it accumulates via device-side atomics and syncs
244  // back to PETSc before the CPU path writes. The CPU queries below filter out
245  // Kokkos objects via AttribKokkos(false) so there is no double-counting.
247  computeKokkosLinearSystem(vector_tags, matrix_tags);
248 #endif
249 
250  // linear contributions from the domain
251  PARALLEL_TRY
252  {
253  TIME_SECTION("LinearFVKernels_FullSystem", 3 /*, "Computing LinearFVKernels"*/);
254 
256  ElemInfoRange elem_info_range(_fe_problem.mesh().ownedElemInfoBegin(),
258 
260  FaceInfoRange face_info_range(_fe_problem.mesh().ownedFaceInfoBegin(),
262 
263  ComputeLinearFVElementalThread elem_thread(
264  _fe_problem, this->number(), vector_tags, matrix_tags);
265  Threads::parallel_reduce(elem_info_range, elem_thread);
266 
268  this->number(),
270  vector_tags,
271  matrix_tags);
272  Threads::parallel_reduce(face_info_range, face_thread);
273  }
274  PARALLEL_CATCH;
275 
276  closeTaggedMatrices(matrix_tags);
277 
280 
281  // Accumulate the occurrence of solution invalid warnings for the current iteration cumulative
282  // counters
285 }
286 
289 {
290  return *_rhs_time;
291 }
292 
295 {
296  return *_rhs_non_time;
297 }
298 
299 void
301  std::vector<dof_id_type> & /*n_nz*/,
302  std::vector<dof_id_type> & /*n_oz*/)
303 {
304  mooseError("LinearSystem does not support AugmentSparsity!");
305 }
306 
307 void
309 {
310  TIME_SECTION("LinearSystem::solve", 2, "Solving linear system");
311 
312  // Clear the iteration counters
313  _current_l_its = 0;
314 
315  system().solve();
316 
317  // store info about the solve
319 
320  auto & linear_solver =
321  libMesh::cast_ref<PetscLinearSolver<Real> &>(*_linear_implicit_system.get_linear_solver());
322  _initial_linear_residual = linear_solver.get_initial_residual();
324  _converged = linear_solver.get_converged_reason() > 0;
325 
326  _console << "System: " << this->name() << " Initial residual: " << _initial_linear_residual
327  << " Final residual: " << _final_linear_residual << " Num. of Iter. " << _n_linear_iters
328  << std::endl;
329 
330  // determine whether solution invalid occurs in the converged solution
332 }
333 
334 void
335 LinearSystem::stopSolve(const ExecFlagType & /*exec_flag*/,
336  const std::set<TagID> & vector_tags_to_close)
337 {
338  // We close the containers in case the solve restarts from a failed iteration
339  closeTaggedVectors(vector_tags_to_close);
341 }
342 
343 bool
345 {
346  // Right now, FV kernels are in TheWarehouse so we have to use that.
347  std::vector<LinearFVKernel *> kernels;
348  auto base_query = _fe_problem.theWarehouse()
349  .query()
350  .template condition<AttribSysNum>(this->number())
351  .template condition<AttribSystem>("LinearFVKernel")
352  .queryInto(kernels);
353 
354  bool contains_time_kernel = false;
355  for (const auto kernel : kernels)
356  {
357  contains_time_kernel = dynamic_cast<LinearFVTimeDerivative *>(kernel);
358  if (contains_time_kernel)
359  break;
360  }
361 
362  return contains_time_kernel;
363 }
364 
365 void
367 {
368  // - Linear system assembly is associated with EXEC_NONLINEAR
369  // - Avoid division by 0 dt
370  if (type == EXEC_NONLINEAR && _fe_problem.dt() > 0.)
371  for (auto & ti : _time_integrators)
372  // Do things like compute integration weights
373  ti->preStep();
374 }
std::string name(const ElemQuality q)
std::vector< std::shared_ptr< TimeIntegrator > > _time_integrators
Time integrator.
Definition: SystemBase.h:1049
virtual void stopSolve(const ExecFlagType &exec_flag, const std::set< TagID > &vector_tags_to_close) override
Quit the current solve as soon as possible.
Definition: LinearSystem.C:335
void rebuildLinearFVGradientStorage()
Rebuild persistent raw and temporary gradient storage after mesh/DOF changes.
virtual void preInit() override
This is called prior to the libMesh system has been init&#39;d.
Definition: LinearSystem.C:107
virtual const char * what() const
Get out the error message.
unsigned int n_threads()
unsigned int _n_linear_iters
Number of linear iterations.
Definition: LinearSystem.h:235
void checkInvalidSolution()
Definition: SolverSystem.C:165
face_info_iterator ownedFaceInfoBegin()
Iterators to owned faceInfo objects.
Definition: MooseMesh.C:1498
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
void accumulateIterationIntoTimeStepOccurences()
Pass the number of solution invalid occurrences from current iteration to cumulative counters...
virtual bool containsTimeKernel() override
If the system has a kernel that corresponds to a time derivative.
Definition: LinearSystem.C:344
NumericVector< Number > & getRightHandSideNonTimeVector()
Return a numeric vector that is associated with the nontime tag.
Definition: LinearSystem.C:294
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition: SubProblem.C:93
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:312
virtual void associateVectorToTag(NumericVector< Number > &vec, TagID tag)
Associate a vector for a given tag.
Definition: SystemBase.C:982
void computeLinearSystemInternal(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags, const bool compute_gradients=true)
Compute the right hand side and system matrix for given tags.
Definition: LinearSystem.C:211
virtual void compute(ExecFlagType type) override
Compute time derivatives, auxiliary variables, etc.
Definition: LinearSystem.C:366
void compute_linear_system(libMesh::EquationSystems &es, const std::string &system_name)
Definition: LinearSystem.C:67
NumericVector< Number > * rhs
virtual LinearSolver< Number > * get_linear_solver() const override
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
unsigned int _current_l_its
The linear iterations needed for convergence.
Definition: LinearSystem.h:205
void initialSetupKokkosLinearFV()
Perform the initial setup of the Kokkos linear finite volume kernels and boundary conditions...
Base class for a system (of equations)
Definition: SystemBase.h:85
Real _initial_linear_residual
The initial linear residual.
Definition: LinearSystem.h:238
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
Scope guard for starting and stopping Floating Point Exception Trapping.
virtual void zero()=0
elem_info_iterator ownedElemInfoBegin()
Iterators to owned faceInfo objects.
Definition: MooseMesh.C:1516
Adds contributions from volumetric terms discretized using the finite volume method to the matrix and...
System & _sys
Base class reference to the libmesh system.
Definition: LinearSystem.h:202
virtual void initialSetup() override
Setup Functions.
Definition: LinearSystem.C:118
virtual void computeLinearSystemSys(libMesh::LinearImplicitSystem &sys, libMesh::SparseMatrix< libMesh::Number > &system_matrix, NumericVector< libMesh::Number > &rhs, const bool compute_gradients=true)
Assemble both the right hand side and the system matrix of a given linear system. ...
virtual void activateAllMatrixTags()
Make all existing matrices active.
Definition: SystemBase.C:1132
virtual const std::string & name() const
Definition: SystemBase.C:1342
void closeTaggedMatrices(const std::set< TagID > &tags)
Close all matrices associated the tags.
Definition: SystemBase.C:1061
void syncIteration()
Sync iteration counts to main processor Sum across all processors.
libMesh::LinearImplicitSystem & _linear_implicit_system
Base class reference to the linear implicit system in libmesh.
Definition: LinearSystem.h:247
NumericVector< Number > * _rhs_time
right hand side vector for time contributions
Definition: LinearSystem.h:217
const T & get(std::string_view) const
virtual void zero()=0
TheWarehouse & theWarehouse() const
unsigned int n_linear_iterations() const
Real _final_linear_residual
The final linear residual.
Definition: LinearSystem.h:241
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition: MooseApp.h:185
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Definition: SubProblem.C:312
TagID _rhs_tag
Used for the right hand side vector from PETSc.
Definition: LinearSystem.h:226
bool errorOnJacobianNonzeroReallocation() const
Will return True if the user wants to get an error when a nonzero is reallocated in the Jacobian by P...
unsigned int number() const
Gets the number of this system.
Definition: SystemBase.C:1158
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
virtual void solve() override
Solve the system (using libMesh magic)
Definition: LinearSystem.C:308
void closeTaggedVectors(const std::set< TagID > &tags)
Close all vectors for given tags.
Definition: SystemBase.C:668
Interface for objects interacting with the PerfGraph.
virtual void solve()
virtual void close()=0
LinearSystem & getLinearSystem(unsigned int sys_num)
Get non-constant reference to a linear system.
const NumericVector< Number > * _current_solution
solution vector from solver
Definition: SolverSystem.h:120
Kernel that adds contributions from a time derivative term to a linear system populated using the fin...
TagID _system_matrix_tag
Tag for every contribution to system matrix.
Definition: LinearSystem.h:232
const ExecFlagType EXEC_NONLINEAR
Definition: Moose.C:33
MooseApp & _app
Definition: SystemBase.h:988
FEProblemBase & _fe_problem
the governing finite element/volume problem
Definition: SystemBase.h:986
bool _converged
If the solve on the linear system converged.
Definition: LinearSystem.h:244
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.
NumericVector< Number > * _rhs_non_time
right hand side vector for non-time contributions
Definition: LinearSystem.h:223
virtual void close()=0
virtual void reinit() override
Reinitialize the system when the degrees of freedom in this system have changed.
Definition: LinearSystem.C:178
Class for containing MooseEnum item information.
Definition: MooseEnumItem.h:18
NumericVector< Number > & getRightHandSideTimeVector()
Return a numeric vector that is associated with the time tag.
Definition: LinearSystem.C:288
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:1025
bool hasKokkosResidualObjects() const
SparseMatrix< Number > * matrix
void setCurrentLinearSystem(unsigned int sys_num)
Set the current linear system pointer.
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse...
Definition: TheWarehouse.h:467
virtual MooseMesh & mesh() override
unsigned int linearSysNum(const LinearSystemName &linear_sys_name) const override
virtual void preInit() override
This is called prior to the libMesh system has been init&#39;d.
Definition: SolverSystem.C:32
std::unique_ptr< NumericVector< Number > > current_local_solution
virtual void augmentSparsity(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.
Definition: LinearSystem.C:300
Adds contributions from face terms discretized using the finite volume method to the matrix and right...
elem_info_iterator ownedElemInfoEnd()
Definition: MooseMesh.C:1524
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.
face_info_iterator ownedFaceInfoEnd()
Definition: MooseMesh.C:1507
void computeKokkosLinearSystem(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags)
Assemble the Kokkos contributions to the linear system for the given tags.
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition: SystemBase.C:91
void full_sparsity_pattern_needed()
virtual ~LinearSystem()
virtual void initialSetup()
Setup Functions.
Definition: SystemBase.C:1560
virtual Real & dt() const
const DofMap & get_dof_map() const
LinearSystem(FEProblemBase &problem, const std::string &name)
Definition: LinearSystem.C:78
virtual System & system() override
Get the reference to the libMesh system.
Definition: LinearSystem.h:146
void computeLinearSystemTags(const std::set< TagID > &vector_tags, const std::set< TagID > &matrix_tags, const bool compute_gradients=true)
Compute the right hand side and the system matrix of the system for given tags.
Definition: LinearSystem.C:185
unsigned int THREAD_ID
Definition: MooseTypes.h:237
void computeGradients()
Compute and store raw and requested limited Green-Gauss gradients for linear FV variables.
Shared storage and allocation logic for linear finite-volume cell gradients for variables in the syst...