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"
21 #include "DisplacedProblem.h"
22 #include "Parser.h"
23 #include "MooseMesh.h"
24 #include "MooseUtils.h"
25 #include "MooseApp.h"
26 #include "TimeIntegrator.h"
27 #include "Assembly.h"
29 #include "Moose.h"
30 #include "ConsoleStream.h"
31 #include "MooseError.h"
33 #include "LinearFVFluxKernel.h"
34 #include "UserObject.h"
35 #include "SolutionInvalidity.h"
36 #include "MooseLinearVariableFV.h"
37 #include "LinearFVTimeDerivative.h"
38 #include "LinearFVFluxKernel.h"
41 
42 // libMesh
43 #include "libmesh/linear_solver.h"
44 #include "libmesh/quadrature_gauss.h"
45 #include "libmesh/dense_vector.h"
46 #include "libmesh/boundary_info.h"
47 #include "libmesh/petsc_matrix.h"
48 #include "libmesh/petsc_vector.h"
49 #include "libmesh/petsc_nonlinear_solver.h"
50 #include "libmesh/numeric_vector.h"
51 #include "libmesh/mesh.h"
52 #include "libmesh/dense_subvector.h"
53 #include "libmesh/dense_submatrix.h"
54 #include "libmesh/dof_map.h"
55 #include "libmesh/sparse_matrix.h"
56 #include "libmesh/petsc_matrix.h"
57 #include "libmesh/default_coupling.h"
58 #include "libmesh/diagonal_matrix.h"
59 #include "libmesh/petsc_solver_exception.h"
60 
61 #include <ios>
62 
63 using namespace libMesh;
64 
65 namespace Moose
66 {
67 void
68 compute_linear_system(libMesh::EquationSystems & es, const std::string & system_name)
69 {
70  FEProblemBase * p = es.parameters.get<FEProblemBase *>("_fe_problem_base");
71  auto & sys = p->getLinearSystem(p->linearSysNum(system_name));
72  auto & lin_sys = sys.linearImplicitSystem();
73  auto & matrix = *(sys.linearImplicitSystem().matrix);
74  auto & rhs = *(sys.linearImplicitSystem().rhs);
75  p->computeLinearSystemSys(lin_sys, matrix, rhs);
76 }
77 }
78 
79 LinearSystem::LinearSystem(FEProblemBase & fe_problem, const std::string & name)
80  : SolverSystem(fe_problem, fe_problem, name, Moose::VAR_SOLVER),
81  PerfGraphInterface(fe_problem.getMooseApp().perfGraph(), "LinearSystem"),
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  // Checking if somebody accidentally assigned nonlinear variables to this system
111  const auto & var_names = _vars[0].names();
112  for (const auto & name : var_names)
113  if (!dynamic_cast<MooseLinearVariableFVReal *>(_vars[0].getVariable(name)))
114  mooseError("You are trying to add a nonlinear variable to a linear system! The variable "
115  "which is assigned to the wrong system: ",
116  name);
117 
118  // Calling initial setup for the linear kernels
119  for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
120  {
121  std::vector<LinearFVElementalKernel *> fv_elemental_kernels;
123  .query()
124  .template condition<AttribSystem>("LinearFVElementalKernel")
125  .template condition<AttribThread>(tid)
126  .queryInto(fv_elemental_kernels);
127 
128  for (auto * fv_kernel : fv_elemental_kernels)
129  fv_kernel->initialSetup();
130 
131  std::vector<LinearFVFluxKernel *> fv_flux_kernels;
133  .query()
134  .template condition<AttribSystem>("LinearFVFluxKernel")
135  .template condition<AttribThread>(tid)
136  .queryInto(fv_flux_kernels);
137 
138  for (auto * fv_kernel : fv_flux_kernels)
139  fv_kernel->initialSetup();
140 
141  std::vector<LinearFVBoundaryCondition *> fv_bcs;
143  .query()
144  .template condition<AttribSystem>("LinearFVBoundaryCondition")
145  .template condition<AttribThread>(tid)
146  .queryInto(fv_bcs);
147 
148  for (auto * fv_bc : fv_bcs)
149  fv_bc->initialSetup();
150  }
151 }
152 
153 void
154 LinearSystem::computeLinearSystemTags(const std::set<TagID> & vector_tags,
155  const std::set<TagID> & matrix_tags,
156  const bool compute_gradients)
157 {
158  parallel_object_only();
159 
160  TIME_SECTION("LinearSystem::computeLinearSystemTags", 5);
161 
163 
165 
166  try
167  {
168  computeLinearSystemInternal(vector_tags, matrix_tags, compute_gradients);
169  }
170  catch (MooseException & e)
171  {
172  _console << "Exception detected " << e.what() << std::endl;
173  // The buck stops here, we have already handled the exception by
174  // calling stopSolve(), it is now up to PETSc to return a
175  // "diverged" reason during the next solve.
176  }
177 }
178 
179 void
181 {
182  _new_gradient.clear();
183  for (auto & vec : _raw_grad_container)
184  _new_gradient.push_back(vec->zero_clone());
185 
186  TIME_SECTION("LinearVariableFV_Gradients", 3 /*, "Computing Linear FV variable gradients"*/);
187 
188  PARALLEL_TRY
189  {
191  FaceInfoRange face_info_range(_fe_problem.mesh().ownedFaceInfoBegin(),
193 
194  ComputeLinearFVGreenGaussGradientFaceThread gradient_face_thread(
196  Threads::parallel_reduce(face_info_range, gradient_face_thread);
197  }
198  PARALLEL_CATCH;
199 
200  for (auto & vec : _new_gradient)
201  vec->close();
202 
203  PARALLEL_TRY
204  {
206  ElemInfoRange elem_info_range(_fe_problem.mesh().ownedElemInfoBegin(),
208 
209  ComputeLinearFVGreenGaussGradientVolumeThread gradient_volume_thread(
211  Threads::parallel_reduce(elem_info_range, gradient_volume_thread);
212  }
213  PARALLEL_CATCH;
214 
215  for (const auto i : index_range(_raw_grad_container))
216  {
217  _new_gradient[i]->close();
218  _raw_grad_container[i] = std::move(_new_gradient[i]);
219  }
220 }
221 
222 void
223 LinearSystem::computeLinearSystemInternal(const std::set<TagID> & vector_tags,
224  const std::set<TagID> & matrix_tags,
225  const bool compute_gradients)
226 {
227  TIME_SECTION("computeLinearSystemInternal", 3);
228 
229  // Before we assemble we clear up the matrix and the vector
232 
233  // Make matrix ready to use
235 
236  for (auto tag : matrix_tags)
237  {
238  auto & matrix = getMatrix(tag);
239  // Necessary for speed
240  if (auto petsc_matrix = dynamic_cast<PetscMatrix<Number> *>(&matrix))
241  {
242  LibmeshPetscCall(MatSetOption(petsc_matrix->mat(),
243  MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
244  PETSC_TRUE));
246  LibmeshPetscCall(
247  MatSetOption(petsc_matrix->mat(), MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
248  }
249  }
250 
251  if (compute_gradients)
253 
254  // linear contributions from the domain
255  PARALLEL_TRY
256  {
257  TIME_SECTION("LinearFVKernels_FullSystem", 3 /*, "Computing LinearFVKernels"*/);
258 
260  ElemInfoRange elem_info_range(_fe_problem.mesh().ownedElemInfoBegin(),
262 
264  FaceInfoRange face_info_range(_fe_problem.mesh().ownedFaceInfoBegin(),
266 
267  ComputeLinearFVElementalThread elem_thread(
268  _fe_problem, this->number(), vector_tags, matrix_tags);
269  Threads::parallel_reduce(elem_info_range, elem_thread);
270 
272  this->number(),
274  vector_tags,
275  matrix_tags);
276  Threads::parallel_reduce(face_info_range, face_thread);
277  }
278  PARALLEL_CATCH;
279 
280  closeTaggedMatrices(matrix_tags);
281 
284 
285  // Accumulate the occurrence of solution invalid warnings for the current iteration cumulative
286  // counters
289 }
290 
293 {
294  return *_rhs_time;
295 }
296 
299 {
300  return *_rhs_non_time;
301 }
302 
303 void
305  std::vector<dof_id_type> & /*n_nz*/,
306  std::vector<dof_id_type> & /*n_oz*/)
307 {
308  mooseError("LinearSystem does not support AugmentSparsity!");
309 }
310 
311 void
313 {
314  TIME_SECTION("LinearSystem::solve", 2, "Solving linear system");
315 
316  // Clear the iteration counters
317  _current_l_its = 0;
318 
319  system().solve();
320 
321  // store info about the solve
323 
324  auto & linear_solver =
325  libMesh::cast_ref<PetscLinearSolver<Real> &>(*_linear_implicit_system.get_linear_solver());
326  _initial_linear_residual = linear_solver.get_initial_residual();
328  _converged = linear_solver.get_converged_reason() > 0;
329 
330  _console << "System: " << this->name() << " Initial residual: " << _initial_linear_residual
331  << " Final residual: " << _final_linear_residual << " Num. of Iter. " << _n_linear_iters
332  << std::endl;
333 
334  // determine whether solution invalid occurs in the converged solution
336 }
337 
338 void
339 LinearSystem::stopSolve(const ExecFlagType & /*exec_flag*/,
340  const std::set<TagID> & vector_tags_to_close)
341 {
342  // We close the containers in case the solve restarts from a failed iteration
343  closeTaggedVectors(vector_tags_to_close);
345 }
346 
347 bool
349 {
350  // Right now, FV kernels are in TheWarehouse so we have to use that.
351  std::vector<LinearFVKernel *> kernels;
352  auto base_query = _fe_problem.theWarehouse()
353  .query()
354  .template condition<AttribSysNum>(this->number())
355  .template condition<AttribSystem>("LinearFVKernel")
356  .queryInto(kernels);
357 
358  bool contains_time_kernel = false;
359  for (const auto kernel : kernels)
360  {
361  contains_time_kernel = dynamic_cast<LinearFVTimeDerivative *>(kernel);
362  if (contains_time_kernel)
363  break;
364  }
365 
366  return contains_time_kernel;
367 }
368 
369 void
371 {
372  // Linear systems have their own time derivative computation machinery
373 }
std::string name(const ElemQuality q)
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:339
The gradient in a volume using Green Gauss theorem and a cell-centered finite-volume approximation ca...
virtual const char * what() const
Get out the error message.
unsigned int n_threads()
void computeGradients()
Compute the Green-Gauss gradients.
Definition: LinearSystem.C:180
unsigned int _n_linear_iters
Number of linear iterations.
Definition: LinearSystem.h:190
void checkInvalidSolution()
Definition: SolverSystem.C:111
face_info_iterator ownedFaceInfoBegin()
Iterators to owned faceInfo objects.
Definition: MooseMesh.C:1560
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:323
virtual bool containsTimeKernel() override
If the system has a kernel that corresponds to a time derivative.
Definition: LinearSystem.C:348
The gradient in a volume using Green Gauss theorem and a cell-centered finite-volume approximation ca...
NumericVector< Number > & getRightHandSideNonTimeVector()
Return a numeric vector that is associated with the nontime tag.
Definition: LinearSystem.C:298
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:311
virtual void associateVectorToTag(NumericVector< Number > &vec, TagID tag)
Associate a vector for a given tag.
Definition: SystemBase.C:981
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:223
virtual void compute(ExecFlagType type) override
Compute time derivatives, auxiliary variables, etc.
Definition: LinearSystem.C:370
void compute_linear_system(libMesh::EquationSystems &es, const std::string &system_name)
Definition: LinearSystem.C:68
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:160
std::vector< std::unique_ptr< NumericVector< Number > > > _raw_grad_container
A cache for storing gradients at dof locations.
Definition: SystemBase.h:1073
Real _initial_linear_residual
The initial linear residual.
Definition: LinearSystem.h:193
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
std::vector< std::unique_ptr< NumericVector< Number > > > _new_gradient
Vectors to store the new gradients during the computation.
Definition: LinearSystem.h:208
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:1578
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:1131
virtual const std::string & name() const
Definition: SystemBase.C:1340
void closeTaggedMatrices(const std::set< TagID > &tags)
Close all matrices associated the tags.
Definition: SystemBase.C:1060
void solutionInvalidAccumulation()
Pass the number of solution invalid occurrences from current iteration to cumulative counters...
void syncIteration()
Sync iteration counts to main processor.
libMesh::LinearImplicitSystem & _linear_implicit_system
Base class reference to the linear implicit system in libmesh.
Definition: LinearSystem.h:202
NumericVector< Number > * _rhs_time
right hand side vector for time contributions
Definition: LinearSystem.h:172
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:196
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition: MooseApp.h:179
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:181
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:1157
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:312
void closeTaggedVectors(const std::set< TagID > &tags)
Close all vectors for given tags.
Definition: SystemBase.C:667
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.
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:187
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:199
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:178
virtual void close()=0
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:292
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
Definition: SystemBase.C:1024
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:466
virtual MooseMesh & mesh() override
unsigned int linearSysNum(const LinearSystemName &linear_sys_name) const override
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:304
Adds contributions from face terms discretized using the finite volume method to the matrix and right...
elem_info_iterator ownedElemInfoEnd()
Definition: MooseMesh.C:1586
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:1569
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
virtual ~LinearSystem()
virtual void initialSetup()
Setup Functions.
Definition: SystemBase.C:1558
LinearSystem(FEProblemBase &problem, const std::string &name)
Definition: LinearSystem.C:79
auto index_range(const T &sizable)
virtual System & system() override
Get the reference to the libMesh system.
Definition: LinearSystem.h:107
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:154
unsigned int THREAD_ID
Definition: MooseTypes.h:237