https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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"
36#include "LinearFVFluxKernel.h"
39
40// libMesh
41#include "libmesh/linear_solver.h"
42#include "libmesh/quadrature_gauss.h"
43#include "libmesh/dense_vector.h"
44#include "libmesh/boundary_info.h"
45#include "libmesh/petsc_matrix.h"
46#include "libmesh/petsc_vector.h"
47#include "libmesh/petsc_nonlinear_solver.h"
48#include "libmesh/numeric_vector.h"
49#include "libmesh/mesh.h"
50#include "libmesh/dense_subvector.h"
51#include "libmesh/dense_submatrix.h"
52#include "libmesh/dof_map.h"
53#include "libmesh/sparse_matrix.h"
54#include "libmesh/petsc_matrix.h"
55#include "libmesh/default_coupling.h"
56#include "libmesh/diagonal_matrix.h"
57#include "libmesh/petsc_solver_exception.h"
58
59#include <ios>
60
61namespace Moose
62{
63void
64compute_linear_system(libMesh::EquationSystems & es, const std::string & system_name)
65{
66 FEProblemBase * p = es.parameters.get<FEProblemBase *>("_fe_problem_base");
67 auto & sys = p->getLinearSystem(p->linearSysNum(system_name));
68 auto & lin_sys = sys.linearImplicitSystem();
69 auto & matrix = *(sys.linearImplicitSystem().matrix);
70 auto & rhs = *(sys.linearImplicitSystem().rhs);
71 p->computeLinearSystemSys(lin_sys, matrix, rhs);
72}
73}
74
75LinearSystem::LinearSystem(FEProblemBase & fe_problem, const std::string & name)
76 : SolverSystem(fe_problem, fe_problem, name, Moose::VAR_SOLVER),
77 PerfGraphInterface(fe_problem.getMooseApp().perfGraph(), "LinearSystem"),
78 LinearFVGradientManager(cast_ref<SystemBase &>(*this)),
79 _sys(fe_problem.es().add_system<LinearImplicitSystem>(name)),
80 _rhs_time_tag(-1),
81 _rhs_time(NULL),
82 _rhs_non_time_tag(-1),
83 _rhs_non_time(NULL),
84 _n_linear_iters(0),
85 _converged(false),
86 _linear_implicit_system(fe_problem.es().get_system<LinearImplicitSystem>(name))
87{
89 // Don't need to add the matrix - it already exists. Well, technically it will exist
90 // after the initialization. Right now it is just a nullpointer. We will just make sure
91 // we associate the tag with the system matrix for now.
93
94 // We create a tag for the right hand side, the vector is already in the libmesh system
97
99}
100
102
103void
105{
107
108#ifdef MOOSE_KOKKOS_ENABLED
110 _sys.get_dof_map().full_sparsity_pattern_needed();
111#endif
112}
113
114void
120
121void
123{
125 _current_solution = system().current_local_solution.get();
127 // Checking if somebody accidentally assigned nonlinear variables to this system
128 const auto & var_names = _vars[0].names();
129 for (const auto & name : var_names)
130 if (!dynamic_cast<MooseLinearVariableFVReal *>(_vars[0].getVariable(name)))
131 mooseError("You are trying to add a nonlinear variable to a linear system! The variable "
132 "which is assigned to the wrong system: ",
133 name);
134
135 // Calling initial setup for the linear kernels
136 for (THREAD_ID tid = 0; tid < libMesh::n_threads(); tid++)
137 {
138 std::vector<LinearFVElementalKernel *> fv_elemental_kernels;
140 .query()
141 .template condition<AttribSysNum>(number())
142 .template condition<AttribSystem>("LinearFVElementalKernel")
143 .template condition<AttribKokkos>(false)
144 .template condition<AttribThread>(tid)
145 .queryInto(fv_elemental_kernels);
146
147 for (auto * fv_kernel : fv_elemental_kernels)
148 fv_kernel->initialSetup();
149
150 std::vector<LinearFVFluxKernel *> fv_flux_kernels;
152 .query()
153 .template condition<AttribSysNum>(number())
154 .template condition<AttribSystem>("LinearFVFluxKernel")
155 .template condition<AttribKokkos>(false)
156 .template condition<AttribThread>(tid)
157 .queryInto(fv_flux_kernels);
158
159 for (auto * fv_kernel : fv_flux_kernels)
160 fv_kernel->initialSetup();
161
162 std::vector<LinearFVBoundaryCondition *> fv_bcs;
164 .query()
165 .template condition<AttribSysNum>(number())
166 .template condition<AttribSystem>("LinearFVBoundaryCondition")
167 .template condition<AttribKokkos>(false)
168 .template condition<AttribThread>(tid)
169 .queryInto(fv_bcs);
170
171 for (auto * fv_bc : fv_bcs)
172 fv_bc->initialSetup();
173 }
174
175#ifdef MOOSE_KOKKOS_ENABLED
177#endif
178}
179
180void
186
187void
189 const bool skip_current_to_old)
190{
191 if (iteration_type == Moose::SolutionIterationType::Time)
192 LinearFVGradientManager::copyPreviousGradientStates(iteration_type, skip_current_to_old);
193}
194
195void
200
201void
202LinearSystem::computeLinearSystemTags(const std::set<TagID> & vector_tags,
203 const std::set<TagID> & matrix_tags,
204 const bool compute_gradients)
205{
206 parallel_object_only();
207
208 TIME_SECTION("LinearSystem::computeLinearSystemTags", 5);
209
211
213
214 try
215 {
216 computeLinearSystemInternal(vector_tags, matrix_tags, compute_gradients);
217 }
218 catch (MooseException & e)
219 {
220 _console << "Exception detected " << e.what() << std::endl;
221 // The buck stops here, we have already handled the exception by
222 // calling stopSolve(), it is now up to PETSc to return a
223 // "diverged" reason during the next solve.
224 }
225}
226
227void
228LinearSystem::computeLinearSystemInternal(const std::set<TagID> & vector_tags,
229 const std::set<TagID> & matrix_tags,
230 const bool compute_gradients)
231{
232 TIME_SECTION("computeLinearSystemInternal", 3);
233
234 // Before we assemble we clear up the matrix and the vector
237
238 // Make matrix ready to use
240
241 for (auto tag : matrix_tags)
242 {
243 auto & matrix = getMatrix(tag);
244 // Necessary for speed
245 if (auto petsc_matrix = dynamic_cast<PetscMatrix<Number> *>(&matrix))
246 {
247 LibmeshPetscCall(MatSetOption(petsc_matrix->mat(),
248 MAT_KEEP_NONZERO_PATTERN, // This is changed in 3.1
249 PETSC_TRUE));
251 LibmeshPetscCall(
252 MatSetOption(petsc_matrix->mat(), MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
253 }
254 }
255
256 if (compute_gradients)
258
259#ifdef MOOSE_KOKKOS_ENABLED
260 // Kokkos assembly runs first: it accumulates via device-side atomics and syncs
261 // back to PETSc before the CPU path writes. The CPU queries below filter out
262 // Kokkos objects via AttribKokkos(false) so there is no double-counting.
264 computeKokkosLinearSystem(vector_tags, matrix_tags);
265#endif
266
267 // linear contributions from the domain
268 PARALLEL_TRY
269 {
270 TIME_SECTION("LinearFVKernels_FullSystem", 3 /*, "Computing LinearFVKernels"*/);
271
272 using ElemInfoRange = StoredRange<MooseMesh::const_elem_info_iterator, const ElemInfo *>;
273 ElemInfoRange elem_info_range(_fe_problem.mesh().ownedElemInfoBegin(),
275
276 using FaceInfoRange = StoredRange<MooseMesh::const_face_info_iterator, const FaceInfo *>;
277 FaceInfoRange face_info_range(_fe_problem.mesh().ownedFaceInfoBegin(),
279
281 _fe_problem, this->number(), vector_tags, matrix_tags);
282 Threads::parallel_reduce(elem_info_range, elem_thread);
283
285 this->number(),
287 vector_tags,
288 matrix_tags);
289 Threads::parallel_reduce(face_info_range, face_thread);
290 }
291 PARALLEL_CATCH;
292
293 closeTaggedMatrices(matrix_tags);
294
297
298 // Accumulate the occurrence of solution invalid warnings for the current iteration cumulative
299 // counters
302}
303
304NumericVector<Number> &
309
310NumericVector<Number> &
315
316void
318 std::vector<dof_id_type> & /*n_nz*/,
319 std::vector<dof_id_type> & /*n_oz*/)
320{
321 mooseError("LinearSystem does not support AugmentSparsity!");
322}
323
324void
326{
327 TIME_SECTION("LinearSystem::solve", 2, "Solving linear system");
328
329 // Clear the iteration counters
330 _current_l_its = 0;
331
332 system().solve();
333
334 // store info about the solve
336
337 auto & linear_solver =
338 cast_ref<libMesh::PetscLinearSolver<Real> &>(*_linear_implicit_system.get_linear_solver());
339 _initial_linear_residual = linear_solver.get_initial_residual();
341 _converged = linear_solver.get_converged_reason() > 0;
342
343 _console << "System: " << this->name() << " Initial residual: " << _initial_linear_residual
344 << " Final residual: " << _final_linear_residual << " Num. of Iter. " << _n_linear_iters
345 << std::endl;
346
347 // determine whether solution invalid occurs in the converged solution
349}
350
351void
353 const std::set<TagID> & vector_tags_to_close)
354{
355 // We close the containers in case the solve restarts from a failed iteration
356 closeTaggedVectors(vector_tags_to_close);
358}
359
360bool
362{
363 // Right now, FV kernels are in TheWarehouse so we have to use that.
364 std::vector<LinearFVKernel *> kernels;
365 auto base_query = _fe_problem.theWarehouse()
366 .query()
367 .template condition<AttribSysNum>(this->number())
368 .template condition<AttribSystem>("LinearFVKernel")
369 .queryInto(kernels);
370
371 bool contains_time_kernel = false;
372 for (const auto kernel : kernels)
373 {
374 contains_time_kernel = dynamic_cast<LinearFVTimeDerivative *>(kernel);
375 if (contains_time_kernel)
376 break;
377 }
378
379 return contains_time_kernel;
380}
381
382void
384{
385 // - Linear system assembly is associated with EXEC_NONLINEAR
386 // - Avoid division by 0 dt
387 if (type == EXEC_NONLINEAR && _fe_problem.dt() > 0.)
388 for (auto & ti : _time_integrators)
389 // Do things like compute integration weights
390 ti->preStep();
391}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
unsigned int THREAD_ID
Definition MooseTypes.h:237
const ExecFlagType EXEC_NONLINEAR
Definition Moose.C:34
Adds contributions from volumetric terms discretized using the finite volume method to the matrix and...
Adds contributions from face terms discretized using the finite volume method to the matrix and right...
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
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.
LinearSystem & getLinearSystem(unsigned int sys_num)
Get non-constant reference to a linear system.
virtual Real & dt() const
bool hasKokkosResidualObjects() const
void setCurrentLinearSystem(unsigned int sys_num)
Set the current linear system pointer.
unsigned int linearSysNum(const LinearSystemName &linear_sys_name) const override
virtual MooseMesh & mesh() override
bool errorOnJacobianNonzeroReallocation() const
Will return True if the user wants to get an error when a nonzero is reallocated in the Jacobian by P...
TheWarehouse & theWarehouse() const
Scope guard for starting and stopping Floating Point Exception Trapping.
Registration, update, and allocation logic for linear finite-volume cell gradients.
void rebuildLinearFVGradientStorage()
Rebuild cached gradient values and reusable scratch storage after mesh/DOF changes.
void copyPreviousGradientStates(Moose::SolutionIterationType iteration_type, bool skip_current_to_old)
Copy published gradient values into requested older states.
void restoreGradientStates()
Restore current gradients from state one after a failed timestep.
void initializeLinearFVGradientHistoryStorage()
Register named system vectors for requested historical gradient states.
void initializeLinearFVGradientStorage()
Initialize private current and replacement gradient storage.
Kernel that adds contributions from a time derivative term to a linear system populated using the fin...
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.
NumericVector< Number > & getRightHandSideNonTimeVector()
Return a numeric vector that is associated with the nontime tag.
virtual bool containsTimeKernel() override
If the system has a kernel that corresponds to a time derivative.
Real _initial_linear_residual
The initial linear residual.
virtual void initialSetup() override
Setup Functions.
virtual void stopSolve(const ExecFlagType &exec_flag, const std::set< TagID > &vector_tags_to_close) override
Quit the current solve as soon as possible.
TagID _rhs_tag
Used for the right hand side vector from PETSc.
TagID _system_matrix_tag
Tag for every contribution to system matrix.
System & _sys
Base class reference to the libmesh system.
virtual void restoreAdditionalStates() override
Restore system-owned state not represented by solution vectors.
virtual void reinit() override
Reinitialize the system when the degrees of freedom in this system have changed.
virtual void preInit() override
This is called prior to the libMesh system has been init'd.
unsigned int _n_linear_iters
Number of linear iterations.
virtual System & system() override
Get the reference to the libMesh system.
NumericVector< Number > * _rhs_non_time
right hand side vector for non-time contributions
NumericVector< Number > & getRightHandSideTimeVector()
Return a numeric vector that is associated with the time tag.
unsigned int _current_l_its
The linear iterations needed for convergence.
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.
void computeGradients()
Compute and finalize all registered linear FV gradient fields.
virtual void copyAdditionalStateBackwards(Moose::SolutionIterationType iteration_type, bool skip_current_to_old) override
Copy system-owned state not represented by solution vectors.
Real _final_linear_residual
The final linear residual.
libMesh::LinearImplicitSystem & _linear_implicit_system
Base class reference to the linear implicit system in libmesh.
LinearSystem(FEProblemBase &problem, const std::string &name)
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.
bool _converged
If the solve on the linear system converged.
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.
void initialSetupKokkosLinearFV()
Perform the initial setup of the Kokkos linear finite volume kernels and boundary conditions.
virtual void initSolutionState() override
Initializes the solution state.
virtual void compute(ExecFlagType type) override
Compute time derivatives, auxiliary variables, etc.
virtual ~LinearSystem()
NumericVector< Number > * _rhs_time
right hand side vector for time contributions
virtual void solve() override
Solve the system (using libMesh magic)
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition MooseApp.h:185
Class for containing MooseEnum item information.
Provides a way for users to bail out of the current solve.
virtual const char * what() const
Get out the error message.
face_info_iterator ownedFaceInfoEnd()
Definition MooseMesh.C:1512
elem_info_iterator ownedElemInfoEnd()
Definition MooseMesh.C:1529
face_info_iterator ownedFaceInfoBegin()
Iterators to owned faceInfo objects.
Definition MooseMesh.C:1503
elem_info_iterator ownedElemInfoBegin()
Iterators to owned faceInfo objects.
Definition MooseMesh.C:1521
Interface for objects interacting with the PerfGraph.
void accumulateIterationIntoTimeStepOccurences()
Pass the number of solution invalid occurrences from current iteration to cumulative counters.
void syncIteration()
Sync iteration counts to main processor Sum across all processors.
virtual void preInit() override
This is called prior to the libMesh system has been init'd.
void checkInvalidSolution()
const NumericVector< Number > * _current_solution
solution vector from solver
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition SubProblem.C:91
virtual TagID addMatrixTag(TagName tag_name)
Create a Tag.
Definition SubProblem.C:310
Base class for a system (of equations)
Definition SystemBase.h:87
virtual libMesh::SparseMatrix< Number > & getMatrix(TagID tag)
Get a raw SparseMatrix.
MooseApp & _app
FEProblemBase & _fe_problem
the governing finite element/volume problem
std::vector< std::shared_ptr< TimeIntegrator > > _time_integrators
Time integrator.
MooseVariableFieldBase & getVariable(THREAD_ID tid, const std::string &var_name) const
Gets a reference to a variable of with specified name.
Definition SystemBase.C:89
unsigned int number() const
Gets the number of this system.
virtual void activateAllMatrixTags()
Make all existing matrices active.
virtual void initialSetup()
Setup Functions.
virtual void initSolutionState()
Initializes the solution state.
virtual void associateVectorToTag(NumericVector< Number > &vec, TagID tag)
Associate a vector for a given tag.
Definition SystemBase.C:980
void closeTaggedVectors(const std::set< TagID > &tags)
Close all vectors for given tags.
Definition SystemBase.C:666
std::vector< VariableWarehouse > _vars
Variable warehouses (one for each thread)
void closeTaggedMatrices(const std::set< TagID > &tags)
Close all matrices associated the tags.
virtual const std::string & name() const
std::vector< T * > & queryInto(std::vector< T * > &results, Args &&... args)
queryInto executes the query and stores the results in the given vector.
Query query()
query creates and returns an initialized a query object for querying objects from the warehouse.
NumericVector< Number > * rhs
SparseMatrix< Number > * matrix
virtual LinearSolver< Number > * get_linear_solver() const override
unsigned int n_linear_iterations() const
virtual void get(const std::vector< numeric_index_type > &index, T *values) const
virtual void close()=0
virtual void zero()=0
const T & get(std::string_view) const
virtual void close()=0
virtual void zero()=0
void attach_assemble_function(void fptr(EquationSystems &es, const std::string &name))
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
void compute_linear_system(libMesh::EquationSystems &es, const std::string &system_name)
SolutionIterationType
Definition MooseTypes.h:270
void parallel_reduce(const Range &range, Body &body, unsigned int n_threads=libMesh::n_threads())
unsigned int n_threads()