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 {
111  // Checking if somebody accidentally assigned nonlinear variables to this system
112  const auto & var_names = _vars[0].names();
113  for (const auto & name : var_names)
114  if (!dynamic_cast<MooseLinearVariableFVReal *>(_vars[0].getVariable(name)))
115  mooseError("You are trying to add a nonlinear variable to a linear system! The variable "
116  "which is assigned to the wrong system: ",
117  name);
118 
120 
121  // Calling initial setup for the linear kernels
122  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
123  {
124  std::vector<LinearFVElementalKernel *> fv_elemental_kernels;
126  .query()
127  .template condition<AttribSystem>("LinearFVElementalKernel")
128  .template condition<AttribThread>(tid)
129  .queryInto(fv_elemental_kernels);
130 
131  for (auto * fv_kernel : fv_elemental_kernels)
132  fv_kernel->initialSetup();
133 
134  std::vector<LinearFVFluxKernel *> fv_flux_kernels;
136  .query()
137  .template condition<AttribSystem>("LinearFVFluxKernel")
138  .template condition<AttribThread>(tid)
139  .queryInto(fv_flux_kernels);
140 
141  for (auto * fv_kernel : fv_flux_kernels)
142  fv_kernel->initialSetup();
143 
144  std::vector<LinearFVBoundaryCondition *> fv_bcs;
146  .query()
147  .template condition<AttribSystem>("LinearFVBoundaryCondition")
148  .template condition<AttribThread>(tid)
149  .queryInto(fv_bcs);
150 
151  for (auto * fv_bc : fv_bcs)
152  fv_bc->initialSetup();
153  }
154 }
155 
156 void
158 {
161 }
162 
163 void
164 LinearSystem::computeLinearSystemTags(const std::set<TagID> & vector_tags,
165  const std::set<TagID> & matrix_tags,
166  const bool compute_gradients)
167 {
168  parallel_object_only();
169 
170  TIME_SECTION("LinearSystem::computeLinearSystemTags", 5);
171 
173 
175 
176  try
177  {
178  computeLinearSystemInternal(vector_tags, matrix_tags, compute_gradients);
179  }
180  catch (MooseException & e)
181  {
182  _console << "Exception detected " << e.what() << std::endl;
183  // The buck stops here, we have already handled the exception by
184  // calling stopSolve(), it is now up to PETSc to return a
185  // "diverged" reason during the next solve.
186  }
187 }
188 
189 void
190 LinearSystem::computeLinearSystemInternal(const std::set<TagID> & vector_tags,
191  const std::set<TagID> & matrix_tags,
192  const bool compute_gradients)
193 {
194  TIME_SECTION("computeLinearSystemInternal", 3);
195 
196  // Before we assemble we clear up the matrix and the vector
199 
200  // Make matrix ready to use
202 
203  for (auto tag : matrix_tags)
204  {
205  auto & matrix = getMatrix(tag);
206  // Necessary for speed
207  if (auto petsc_matrix = dynamic_cast<PetscMatrix<Number> *>(&matrix))
208  {
209  LibmeshPetscCall(MatSetOption(petsc_matrix->mat(),
210  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
211  PETSC_TRUE));
213  LibmeshPetscCall(
214  MatSetOption(petsc_matrix->mat(), MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
215  }
216  }
217 
218  if (compute_gradients)
220 
221  // linear contributions from the domain
222  PARALLEL_TRY
223  {
224  TIME_SECTION("LinearFVKernels_FullSystem", 3 /*, "Computing LinearFVKernels"*/);
225 
227  ElemInfoRange elem_info_range(_fe_problem.mesh().ownedElemInfoBegin(),
229 
231  FaceInfoRange face_info_range(_fe_problem.mesh().ownedFaceInfoBegin(),
233 
234  ComputeLinearFVElementalThread elem_thread(
235  _fe_problem, this->number(), vector_tags, matrix_tags);
236  Threads::parallel_reduce(elem_info_range, elem_thread);
237 
239  this->number(),
241  vector_tags,
242  matrix_tags);
243  Threads::parallel_reduce(face_info_range, face_thread);
244  }
245  PARALLEL_CATCH;
246 
247  closeTaggedMatrices(matrix_tags);
248 
251 
252  // Accumulate the occurrence of solution invalid warnings for the current iteration cumulative
253  // counters
256 }
257 
260 {
261  return *_rhs_time;
262 }
263 
266 {
267  return *_rhs_non_time;
268 }
269 
270 void
272  std::vector<dof_id_type> & /*n_nz*/,
273  std::vector<dof_id_type> & /*n_oz*/)
274 {
275  mooseError("LinearSystem does not support AugmentSparsity!");
276 }
277 
278 void
280 {
281  TIME_SECTION("LinearSystem::solve", 2, "Solving linear system");
282 
283  // Clear the iteration counters
284  _current_l_its = 0;
285 
286  system().solve();
287 
288  // store info about the solve
290 
291  auto & linear_solver =
292  libMesh::cast_ref<PetscLinearSolver<Real> &>(*_linear_implicit_system.get_linear_solver());
293  _initial_linear_residual = linear_solver.get_initial_residual();
295  _converged = linear_solver.get_converged_reason() > 0;
296 
297  _console << "System: " << this->name() << " Initial residual: " << _initial_linear_residual
298  << " Final residual: " << _final_linear_residual << " Num. of Iter. " << _n_linear_iters
299  << std::endl;
300 
301  // determine whether solution invalid occurs in the converged solution
303 }
304 
305 void
306 LinearSystem::stopSolve(const ExecFlagType & /*exec_flag*/,
307  const std::set<TagID> & vector_tags_to_close)
308 {
309  // We close the containers in case the solve restarts from a failed iteration
310  closeTaggedVectors(vector_tags_to_close);
312 }
313 
314 bool
316 {
317  // Right now, FV kernels are in TheWarehouse so we have to use that.
318  std::vector<LinearFVKernel *> kernels;
319  auto base_query = _fe_problem.theWarehouse()
320  .query()
321  .template condition<AttribSysNum>(this->number())
322  .template condition<AttribSystem>("LinearFVKernel")
323  .queryInto(kernels);
324 
325  bool contains_time_kernel = false;
326  for (const auto kernel : kernels)
327  {
328  contains_time_kernel = dynamic_cast<LinearFVTimeDerivative *>(kernel);
329  if (contains_time_kernel)
330  break;
331  }
332 
333  return contains_time_kernel;
334 }
335 
336 void
338 {
339  // - Linear system assembly is associated with EXEC_NONLINEAR
340  // - Avoid division by 0 dt
341  if (type == EXEC_NONLINEAR && _fe_problem.dt() > 0.)
342  for (auto & ti : _time_integrators)
343  // Do things like compute integration weights
344  ti->preStep();
345 }
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:306
void rebuildLinearFVGradientStorage()
Rebuild persistent raw and temporary gradient storage after mesh/DOF changes.
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:188
void checkInvalidSolution()
Definition: SolverSystem.C:165
face_info_iterator ownedFaceInfoBegin()
Iterators to owned faceInfo objects.
Definition: MooseMesh.C:1527
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:315
NumericVector< Number > & getRightHandSideNonTimeVector()
Return a numeric vector that is associated with the nontime tag.
Definition: LinearSystem.C:265
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:190
virtual void compute(ExecFlagType type) override
Compute time derivatives, auxiliary variables, etc.
Definition: LinearSystem.C:337
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:158
Base class for a system (of equations)
Definition: SystemBase.h:85
Real _initial_linear_residual
The initial linear residual.
Definition: LinearSystem.h:191
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:1545
Adds contributions from volumetric terms discretized using the finite volume method to the matrix and...
virtual void initialSetup() override
Setup Functions.
Definition: LinearSystem.C:107
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:200
NumericVector< Number > * _rhs_time
right hand side vector for time contributions
Definition: LinearSystem.h:170
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:194
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition: MooseApp.h:184
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:179
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:279
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:185
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:197
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:176
virtual void close()=0
virtual void reinit() override
Reinitialize the system when the degrees of freedom in this system have changed.
Definition: LinearSystem.C:157
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:259
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:1025
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
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:271
Adds contributions from face terms discretized using the finite volume method to the matrix and right...
elem_info_iterator ownedElemInfoEnd()
Definition: MooseMesh.C:1553
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:1536
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
virtual ~LinearSystem()
virtual void initialSetup()
Setup Functions.
Definition: SystemBase.C:1560
virtual Real & dt() 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:114
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:164
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...