https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NonlinearSystem.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// moose includes
11#include "NonlinearSystem.h"
12#include "FEProblem.h"
13#include "DisplacedProblem.h"
14#include "TimeIntegrator.h"
16#include "PetscSupport.h"
19#include "MooseVariableScalar.h"
20#include "MooseTypes.h"
21#include "AuxiliarySystem.h"
22#include "Console.h"
23
24#include "libmesh/nonlinear_solver.h"
25#include "libmesh/petsc_nonlinear_solver.h"
26#include "libmesh/sparse_matrix.h"
27#include "libmesh/petsc_matrix.h"
28#include "libmesh/diagonal_matrix.h"
29#include "libmesh/default_coupling.h"
30#include "libmesh/petsc_solver_exception.h"
31
32using namespace libMesh;
33
34namespace Moose
35{
36void
38 SparseMatrix<Number> & jacobian,
40{
41 FEProblemBase * p =
42 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
43 p->computeJacobianSys(sys, soln, jacobian);
44}
45
46void
50{
51 FEProblemBase * p =
52 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
53 p->computeBounds(sys, lower, upper);
54}
55
56void
58{
59 FEProblemBase * p =
60 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
61 p->computeNullSpace(sys, sp);
62}
63
64void
67{
68 FEProblemBase * p =
69 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
70 p->computeTransposeNullSpace(sys, sp);
71}
72
73void
75{
76 FEProblemBase * p =
77 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
78 p->computeNearNullSpace(sys, sp);
79}
80
81void
83 NumericVector<Number> & search_direction,
84 NumericVector<Number> & new_soln,
85 bool & changed_search_direction,
86 bool & changed_new_soln,
88{
89 FEProblemBase * p =
90 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
92 sys, old_soln, search_direction, new_soln, changed_search_direction, changed_new_soln);
93}
94} // namespace Moose
95
96NonlinearSystem::NonlinearSystem(FEProblemBase & fe_problem, const std::string & name)
98 fe_problem, fe_problem.es().add_system<NonlinearImplicitSystem>(name), name),
99 _nl_implicit_sys(fe_problem.es().get_system<NonlinearImplicitSystem>(name)),
100 _nl_residual_functor(_fe_problem),
101 _fd_residual_functor(_fe_problem),
102 _resid_and_jac_functor(_fe_problem),
103 _use_coloring_finite_difference(false)
104{
105 nonlinearSolver()->residual_object = &_nl_residual_functor;
111
112 PetscNonlinearSolver<Real> * petsc_solver =
114 if (petsc_solver)
115 {
116 petsc_solver->set_residual_zero_out(false);
117 petsc_solver->set_jacobian_zero_out(false);
118 petsc_solver->use_default_monitor(false);
119 }
120}
121
123
124void
139
140void
142{
143 // Only attach the postcheck function to the solver if we actually
144 // have dampers or if the FEProblemBase needs to update the solution,
145 // which is also done during the linesearch postcheck. It doesn't
146 // hurt to do this multiple times, it is just setting a pointer.
150
152 {
153 TIME_SECTION("nlPreSMOResidual", 3, "Computing Pre-SMO Residual");
154 // Calculate the pre-SMO residual for use in the convergence criterion.
160 _console << " * Nonlinear |R| = "
161 << Console::outputNorm(std::numeric_limits<Real>::max(), _pre_smo_residual)
162 << " (Before preset BCs, predictors, correctors, and constraints)\n";
163 _console << std::flush;
164 }
165
166 const bool presolve_succeeded = preSolve();
167 if (!presolve_succeeded)
168 return;
169
171
172 const bool time_integrator_solve = std::any_of(_time_integrators.begin(),
173 _time_integrators.end(),
174 [](auto & ti) { return ti->overridesSolve(); });
175 if (time_integrator_solve)
176 mooseAssert(_time_integrators.size() == 1,
177 "If solve is overridden, then there must be only one time integrator");
178
179 if (time_integrator_solve)
180 _time_integrators.front()->solve();
181 else
182 system().solve();
183
184 for (auto & ti : _time_integrators)
185 {
186 if (!ti->overridesSolve())
187 ti->setNumIterationsLastSolve();
188 ti->postSolve();
189 }
190
191 if (!_time_integrators.empty())
192 {
193 _n_iters = _time_integrators.front()->getNumNonlinearIterations();
194 _n_linear_iters = _time_integrators.front()->getNumLinearIterations();
195 }
196 else
197 {
199 _n_linear_iters = _nl_implicit_sys.nonlinear_solver->get_total_linear_iterations();
200 }
201
202 // store info about the solve
204
205 // determine whether solution invalid occurs in the converged solution
207
209 LibmeshPetscCall(MatFDColoringDestroy(&_fdcoloring));
210}
211
212void
214 const std::set<TagID> & vector_tags_to_close)
215{
218
219 if (exec_flag == EXEC_LINEAR || exec_flag == EXEC_POSTCHECK)
220 {
221 LibmeshPetscCall(SNESSetFunctionDomainError(solver.snes()));
222
223 // Clean up by getting vectors into a valid state for a
224 // (possible) subsequent solve.
225 closeTaggedVectors(vector_tags_to_close);
226 }
227 else if (exec_flag == EXEC_NONLINEAR)
228 LibmeshPetscCall(SNESSetJacobianDomainError(solver.snes()));
229 else
230 mooseError("Unsupported execute flag: ", Moose::stringify(exec_flag));
231}
232
233void
235{
236 std::shared_ptr<FiniteDifferencePreconditioner> fdp =
237 std::dynamic_pointer_cast<FiniteDifferencePreconditioner>(_preconditioner);
238 if (!fdp)
239 mooseError("Did not setup finite difference preconditioner, and please add a preconditioning "
240 "block with type = fdp");
241
242 if (fdp->finiteDifferenceType() == "coloring")
243 {
246 }
247
248 else if (fdp->finiteDifferenceType() == "standard")
249 {
252 }
253 else
254 mooseError("Unknown finite difference type");
255}
256
257void
259{
260 // Make sure that libMesh isn't going to override our preconditioner
261 _nl_implicit_sys.nonlinear_solver->jacobian = nullptr;
262
263 PetscNonlinearSolver<Number> * petsc_nonlinear_solver =
265
266 PetscMatrix<Number> * petsc_mat =
268
269 LibmeshPetscCall(SNESSetJacobian(petsc_nonlinear_solver->snes(),
270 petsc_mat->mat(),
271 petsc_mat->mat(),
272 SNESComputeJacobianDefault,
273 nullptr));
274}
275
276void
278{
279 // Make sure that libMesh isn't going to override our preconditioner
280 _nl_implicit_sys.nonlinear_solver->jacobian = nullptr;
281
282 PetscNonlinearSolver<Number> & petsc_nonlinear_solver =
284
285 // Pointer to underlying PetscMatrix type
286 PetscMatrix<Number> * petsc_mat =
288
290
291 if (!petsc_mat)
292 mooseError("Could not convert to Petsc matrix.");
293
294 petsc_mat->close();
295
296 ISColoring iscoloring;
297
298 // PETSc 3.5.x
299 MatColoring matcoloring;
300 LibmeshPetscCallA(_communicator.get(), MatColoringCreate(petsc_mat->mat(), &matcoloring));
301 LibmeshPetscCallA(_communicator.get(), MatColoringSetType(matcoloring, MATCOLORINGLF));
302 LibmeshPetscCallA(_communicator.get(), MatColoringSetFromOptions(matcoloring));
303 LibmeshPetscCallA(_communicator.get(), MatColoringApply(matcoloring, &iscoloring));
304 LibmeshPetscCallA(_communicator.get(), MatColoringDestroy(&matcoloring));
305
306 LibmeshPetscCallA(_communicator.get(),
307 MatFDColoringCreate(petsc_mat->mat(), iscoloring, &_fdcoloring));
308 LibmeshPetscCallA(_communicator.get(), MatFDColoringSetFromOptions(_fdcoloring));
309 // clang-format off
310#if PETSC_VERSION_LESS_THAN(3, 24, 0)
311 LibmeshPetscCallA(_communicator.get(),
312 MatFDColoringSetFunction(_fdcoloring,
313 (PetscErrorCode(*)(void))(void (*)(void))
315 &petsc_nonlinear_solver));
316#else
317 LibmeshPetscCallA(_communicator.get(),
318 MatFDColoringSetFunction(_fdcoloring,
319 (MatFDColoringFn*)
321 &petsc_nonlinear_solver));
322#endif
323 // clang-format on
324 LibmeshPetscCallA(_communicator.get(),
325 MatFDColoringSetUp(petsc_mat->mat(), iscoloring, _fdcoloring));
326 LibmeshPetscCallA(_communicator.get(),
327 SNESSetJacobian(petsc_nonlinear_solver.snes(),
328 petsc_mat->mat(),
329 petsc_mat->mat(),
330 SNESComputeJacobianDefaultColor,
331 _fdcoloring));
332 // PETSc >=3.3.0
333 LibmeshPetscCallA(_communicator.get(), ISColoringDestroy(&iscoloring));
334}
335
336bool
338{
340 return false;
341 // When not computing the residual (for example at the beginning of a time step),
342 // we may be in the process of counting invalid solution warnings, so the call to
343 // acceptInvalidSolution() would fail due to lack of parallel synchronization
344 // TODO: think of a better solution
346 {
347 mooseWarning("The solution is not converged due to the solution being invalid.");
348 return false;
349 }
350 return _nl_implicit_sys.nonlinear_solver->converged;
351}
352
353void
355{
356 nonlinearSolver()->attach_preconditioner(preconditioner);
357}
358
359void
364
365void
370
371SNES
373{
374 PetscNonlinearSolver<Number> * petsc_solver =
376
377 if (petsc_solver)
378 {
379 const char * snes_prefix = nullptr;
380 std::string snes_prefix_str;
381 if (system().prefix_with_name())
382 {
383 snes_prefix_str = system().prefix();
384 snes_prefix = snes_prefix_str.c_str();
385 }
386 return petsc_solver->snes(snes_prefix);
387 }
388 else
389 mooseError("It is not a petsc nonlinear solver");
390}
391
392void
394{
397 "Evaluting the residual and Jacobian together does not make sense for a JFNK solve type in "
398 "which only function evaluations are required, e.g. there is no need to form a matrix");
399
400 nonlinearSolver()->residual_object = nullptr;
401 nonlinearSolver()->jacobian = nullptr;
402 nonlinearSolver()->residual_and_jacobian_object = &_resid_and_jac_functor;
403}
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
const ExecFlagType EXEC_POSTCHECK
Definition Moose.C:35
const ExecFlagType EXEC_LINEAR
Definition Moose.C:31
const ExecFlagType EXEC_NONLINEAR
Definition Moose.C:33
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
static std::string outputNorm(const Real &old_norm, const Real &norm, const unsigned int precision=6)
A helper function for outputting norms in color.
Definition Console.C:619
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual void computeNearNullSpace(libMesh::NonlinearImplicitSystem &sys, std::vector< NumericVector< libMesh::Number > * > &sp)
void needsPreviousNewtonIteration(bool state)
Set a flag that indicated that user required values for the previous Newton iterate.
virtual bool hasException()
Whether or not an exception has occurred.
virtual bool shouldUpdateSolution()
Check to see whether the problem should update the solution.
virtual void computeJacobianSys(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, libMesh::SparseMatrix< libMesh::Number > &jacobian)
Form a Jacobian matrix.
bool acceptInvalidSolution() const
Whether or not to accept the solution based on its invalidity.
bool getFailNextNonlinearConvergenceCheck() const
Whether it will skip further residual evaluations and fail the next nonlinear convergence check(s)
bool hasDampers()
Whether or not this system has dampers.
SolverParams & solverParams(unsigned int solver_sys_num=0)
Get the solver parameters.
virtual void computeNullSpace(libMesh::NonlinearImplicitSystem &sys, std::vector< NumericVector< libMesh::Number > * > &sp)
virtual void computeBounds(libMesh::NonlinearImplicitSystem &sys, NumericVector< libMesh::Number > &lower, NumericVector< libMesh::Number > &upper)
virtual void computePostCheck(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &old_soln, NumericVector< libMesh::Number > &search_direction, NumericVector< libMesh::Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln)
bool useSNESMFReuseBase()
Return a flag that indicates if we are reusing the vector base.
virtual void computeTransposeNullSpace(libMesh::NonlinearImplicitSystem &sys, std::vector< NumericVector< libMesh::Number > * > &sp)
virtual void computeResidualSys(libMesh::NonlinearImplicitSystem &sys, const NumericVector< libMesh::Number > &soln, NumericVector< libMesh::Number > &residual)
This function is called by Libmesh to form a residual.
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition MooseApp.h:185
Class for containing MooseEnum item information.
Nonlinear system to be solved.
bool preSolve()
Perform some steps to get ready for the solver.
bool _use_finite_differenced_preconditioner
Whether or not to use a finite differenced preconditioner.
Real _pre_smo_residual
The pre-SMO residual, see setPreSMOResidual for a detailed explanation.
bool shouldEvaluatePreSMOResidual() const
We offer the option to check convergence against the pre-SMO residual.
std::unique_ptr< libMesh::DiagonalMatrix< Number > > _scaling_matrix
A diagonal matrix used for computing scaling.
virtual libMesh::System & system() override
Get the reference to the libMesh system.
std::shared_ptr< MoosePreconditioner > _preconditioner
Preconditioner.
virtual void potentiallySetupFiniteDifferencing() override
Create finite differencing contexts for assembly of the Jacobian and/or approximating the action of t...
void setupColoringFiniteDifferencedPreconditioner()
According to the nonzero pattern provided in the matrix, a graph is constructed.
ComputeResidualFunctor _nl_residual_functor
virtual libMesh::NonlinearImplicitSystem & sys()
virtual SNES getSNES() override
virtual ~NonlinearSystem()
void setupStandardFiniteDifferencedPreconditioner()
Form preconditioning matrix via a standard finite difference method column-by-column.
virtual void stopSolve(const ExecFlagType &exec_flag, const std::set< TagID > &vector_tags_to_close) override
Quit the current solve as soon as possible.
ComputeResidualAndJacobian _resid_and_jac_functor
virtual void setupFiniteDifferencedPreconditioner() override
ComputeFDResidualFunctor _fd_residual_functor
void computeScalingResidual() override
Compute a "residual" for automatic scaling purposes.
NonlinearSystem(FEProblemBase &problem, const std::string &name)
libMesh::NonlinearImplicitSystem & _nl_implicit_sys
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver() override
virtual void attachPreconditioner(libMesh::Preconditioner< Number > *preconditioner) override
Attach a customized preconditioner that requires physics knowledge.
virtual void solve() override
Solve the system (using libMesh magic)
virtual void residualAndJacobianTogether() override
Call this method if you want the residual and Jacobian to be computed simultaneously.
virtual bool converged() override
Returns the convergence state.
void computeScalingJacobian() override
Compute a "Jacobian" for automatic scaling purposes.
bool _use_coloring_finite_difference
virtual NumericVector< Number > & RHS() override
bool hasSynced() const
Whether the solution invalidity has synchronized iteration counts across MPI processes.
void checkInvalidSolution()
const NumericVector< Number > * _current_solution
solution vector from solver
MooseApp & _app
FEProblemBase & _fe_problem
the governing finite element/volume problem
std::vector< std::shared_ptr< TimeIntegrator > > _time_integrators
Time integrator.
unsigned int number() const
Gets the number of this system.
void closeTaggedVectors(const std::set< TagID > &tags)
Close all vectors for given tags.
Definition SystemBase.C:666
NumericVector< Number > * rhs
const SparseMatrix< Number > & get_system_matrix() const
std::unique_ptr< NonlinearSolver< Number > > nonlinear_solver
unsigned int n_nonlinear_iterations() const
NonlinearImplicitSystem::ComputeResidual * mffd_residual_object
virtual void close()=0
virtual Real l2_norm() const=0
const Parallel::Communicator & _communicator
const T & get(std::string_view) const
void set_residual_zero_out(bool state)
void set_snesmf_reuse_base(bool state)
SNES snes(const char *name=nullptr)
void set_jacobian_zero_out(bool state)
void use_default_monitor(bool state)
std::unique_ptr< NumericVector< Number > > current_local_solution
void prefix_with_name(bool value)
virtual void solve()
std::string prefix() const
const EquationSystems & get_equation_systems() const
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
void compute_nearnullspace(std::vector< NumericVector< Number > * > &sp, NonlinearImplicitSystem &sys)
@ ST_JFNK
Jacobian-Free Newton Krylov.
Definition MooseTypes.h:899
void compute_nullspace(std::vector< NumericVector< Number > * > &sp, NonlinearImplicitSystem &sys)
void compute_jacobian(const NumericVector< Number > &soln, SparseMatrix< Number > &jacobian, NonlinearImplicitSystem &sys)
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64
void compute_postcheck(const NumericVector< Number > &old_soln, NumericVector< Number > &search_direction, NumericVector< Number > &new_soln, bool &changed_search_direction, bool &changed_new_soln, NonlinearImplicitSystem &sys)
void compute_transpose_nullspace(std::vector< NumericVector< Number > * > &sp, NonlinearImplicitSystem &sys)
void compute_bounds(NumericVector< Number > &lower, NumericVector< Number > &upper, NonlinearImplicitSystem &sys)
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
PetscErrorCode libmesh_petsc_snes_fd_residual(SNES, Vec x, Vec r, void *ctx)