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
32namespace Moose
33{
34void
35compute_jacobian(const NumericVector<Number> & soln,
36 SparseMatrix<Number> & jacobian,
37 NonlinearImplicitSystem & sys)
38{
39 FEProblemBase * p =
40 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
41 p->computeJacobianSys(sys, soln, jacobian);
42}
43
44void
45compute_bounds(NumericVector<Number> & lower,
46 NumericVector<Number> & upper,
47 NonlinearImplicitSystem & sys)
48{
49 FEProblemBase * p =
50 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
51 p->computeBounds(sys, lower, upper);
52}
53
54void
55compute_nullspace(std::vector<NumericVector<Number> *> & sp, NonlinearImplicitSystem & sys)
56{
57 FEProblemBase * p =
58 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
59 p->computeNullSpace(sys, sp);
60}
61
62void
63compute_transpose_nullspace(std::vector<NumericVector<Number> *> & sp,
64 NonlinearImplicitSystem & sys)
65{
66 FEProblemBase * p =
67 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
68 p->computeTransposeNullSpace(sys, sp);
69}
70
71void
72compute_nearnullspace(std::vector<NumericVector<Number> *> & sp, NonlinearImplicitSystem & sys)
73{
74 FEProblemBase * p =
75 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
76 p->computeNearNullSpace(sys, sp);
77}
78
79void
80compute_postcheck(const NumericVector<Number> & old_soln,
81 NumericVector<Number> & search_direction,
82 NumericVector<Number> & new_soln,
83 bool & changed_search_direction,
84 bool & changed_new_soln,
85 NonlinearImplicitSystem & sys)
86{
87 FEProblemBase * p =
88 sys.get_equation_systems().parameters.get<FEProblemBase *>("_fe_problem_base");
90 sys, old_soln, search_direction, new_soln, changed_search_direction, changed_new_soln);
91}
92} // namespace Moose
93
94NonlinearSystem::NonlinearSystem(FEProblemBase & fe_problem, const std::string & name)
96 fe_problem, fe_problem.es().add_system<NonlinearImplicitSystem>(name), name),
97 _nl_implicit_sys(fe_problem.es().get_system<NonlinearImplicitSystem>(name)),
98 _nl_residual_functor(_fe_problem),
99 _fd_residual_functor(_fe_problem),
100 _resid_and_jac_functor(_fe_problem),
101 _use_coloring_finite_difference(false)
102{
103 nonlinearSolver()->residual_object = &_nl_residual_functor;
109
111 cast_ptr<libMesh::PetscNonlinearSolver<Real> *>(_nl_implicit_sys.nonlinear_solver.get());
112 if (petsc_solver)
113 {
114 petsc_solver->set_residual_zero_out(false);
115 petsc_solver->set_jacobian_zero_out(false);
116 petsc_solver->use_default_monitor(false);
117 }
118}
119
121
122void
137
138void
140{
141 // Only attach the postcheck function to the solver if we actually
142 // have dampers or if the FEProblemBase needs to update the solution,
143 // which is also done during the linesearch postcheck. It doesn't
144 // hurt to do this multiple times, it is just setting a pointer.
148
150 {
151 TIME_SECTION("nlPreSMOResidual", 3, "Computing Pre-SMO Residual");
152 // Calculate the pre-SMO residual for use in the convergence criterion.
158 _console << " * Nonlinear |R| = "
159 << Console::outputNorm(std::numeric_limits<Real>::max(), _pre_smo_residual)
160 << " (Before preset BCs, predictors, correctors, and constraints)\n";
161 _console << std::flush;
162 }
163
164 const bool presolve_succeeded = preSolve();
165 if (!presolve_succeeded)
166 return;
167
169
170 const bool time_integrator_solve = std::any_of(_time_integrators.begin(),
171 _time_integrators.end(),
172 [](auto & ti) { return ti->overridesSolve(); });
173 if (time_integrator_solve)
174 mooseAssert(_time_integrators.size() == 1,
175 "If solve is overridden, then there must be only one time integrator");
176
177 if (time_integrator_solve)
178 _time_integrators.front()->solve();
179 else
180 system().solve();
181
182 for (auto & ti : _time_integrators)
183 {
184 if (!ti->overridesSolve())
185 ti->setNumIterationsLastSolve();
186 ti->postSolve();
187 }
188
189 if (!_time_integrators.empty())
190 {
191 _n_iters = _time_integrators.front()->getNumNonlinearIterations();
192 _n_linear_iters = _time_integrators.front()->getNumLinearIterations();
193 }
194 else
195 {
197 _n_linear_iters = _nl_implicit_sys.nonlinear_solver->get_total_linear_iterations();
198 }
199
200 // store info about the solve
202
203 // determine whether solution invalid occurs in the converged solution
205
207 LibmeshPetscCall(MatFDColoringDestroy(&_fdcoloring));
208}
209
210void
212 const std::set<TagID> & vector_tags_to_close)
213{
215 cast_ref<libMesh::PetscNonlinearSolver<Real> &>(*sys().nonlinear_solver);
216
217 if (exec_flag == EXEC_LINEAR || exec_flag == EXEC_POSTCHECK)
218 {
219 LibmeshPetscCall(SNESSetFunctionDomainError(solver.snes()));
220
221 // Clean up by getting vectors into a valid state for a
222 // (possible) subsequent solve.
223 closeTaggedVectors(vector_tags_to_close);
224 }
225 else if (exec_flag == EXEC_NONLINEAR)
226 LibmeshPetscCall(SNESSetJacobianDomainError(solver.snes()));
227 else
228 mooseError("Unsupported execute flag: ", Moose::stringify(exec_flag));
229}
230
231void
233{
234 std::shared_ptr<FiniteDifferencePreconditioner> fdp =
235 std::dynamic_pointer_cast<FiniteDifferencePreconditioner>(_preconditioner);
236 if (!fdp)
237 mooseError("Did not setup finite difference preconditioner, and please add a preconditioning "
238 "block with type = fdp");
239
240 if (fdp->finiteDifferenceType() == "coloring")
241 {
244 }
245
246 else if (fdp->finiteDifferenceType() == "standard")
247 {
250 }
251 else
252 mooseError("Unknown finite difference type");
253}
254
255void
257{
258 // Make sure that libMesh isn't going to override our preconditioner
259 _nl_implicit_sys.nonlinear_solver->jacobian = nullptr;
260
261 libMesh::PetscNonlinearSolver<Number> * petsc_nonlinear_solver =
262 cast_ptr<libMesh::PetscNonlinearSolver<Number> *>(_nl_implicit_sys.nonlinear_solver.get());
263
264 PetscMatrix<Number> * petsc_mat =
265 cast_ptr<PetscMatrix<Number> *>(&_nl_implicit_sys.get_system_matrix());
266
267 LibmeshPetscCall(SNESSetJacobian(petsc_nonlinear_solver->snes(),
268 petsc_mat->mat(),
269 petsc_mat->mat(),
270 SNESComputeJacobianDefault,
271 nullptr));
272}
273
274void
276{
277 // Make sure that libMesh isn't going to override our preconditioner
278 _nl_implicit_sys.nonlinear_solver->jacobian = nullptr;
279
280 libMesh::PetscNonlinearSolver<Number> & petsc_nonlinear_solver =
282
283 // Pointer to underlying PetscMatrix type
284 PetscMatrix<Number> * petsc_mat =
285 dynamic_cast<PetscMatrix<Number> *>(&_nl_implicit_sys.get_system_matrix());
286
288
289 if (!petsc_mat)
290 mooseError("Could not convert to Petsc matrix.");
291
292 petsc_mat->close();
293
294 ISColoring iscoloring;
295
296 // PETSc 3.5.x
297 MatColoring matcoloring;
298 LibmeshPetscCallA(_communicator.get(), MatColoringCreate(petsc_mat->mat(), &matcoloring));
299 LibmeshPetscCallA(_communicator.get(), MatColoringSetType(matcoloring, MATCOLORINGLF));
300 LibmeshPetscCallA(_communicator.get(), MatColoringSetFromOptions(matcoloring));
301 LibmeshPetscCallA(_communicator.get(), MatColoringApply(matcoloring, &iscoloring));
302 LibmeshPetscCallA(_communicator.get(), MatColoringDestroy(&matcoloring));
303
304 LibmeshPetscCallA(_communicator.get(),
305 MatFDColoringCreate(petsc_mat->mat(), iscoloring, &_fdcoloring));
306 LibmeshPetscCallA(_communicator.get(), MatFDColoringSetFromOptions(_fdcoloring));
307 // clang-format off
308#if PETSC_VERSION_LESS_THAN(3, 24, 0)
309 LibmeshPetscCallA(_communicator.get(),
310 MatFDColoringSetFunction(_fdcoloring,
311 (PetscErrorCode(*)(void))(void (*)(void))
313 &petsc_nonlinear_solver));
314#else
315 LibmeshPetscCallA(_communicator.get(),
316 MatFDColoringSetFunction(_fdcoloring,
317 (MatFDColoringFn*)
319 &petsc_nonlinear_solver));
320#endif
321 // clang-format on
322 LibmeshPetscCallA(_communicator.get(),
323 MatFDColoringSetUp(petsc_mat->mat(), iscoloring, _fdcoloring));
324 LibmeshPetscCallA(_communicator.get(),
325 SNESSetJacobian(petsc_nonlinear_solver.snes(),
326 petsc_mat->mat(),
327 petsc_mat->mat(),
328 SNESComputeJacobianDefaultColor,
329 _fdcoloring));
330 // PETSc >=3.3.0
331 LibmeshPetscCallA(_communicator.get(), ISColoringDestroy(&iscoloring));
332}
333
334bool
336{
338 return false;
339 // When not computing the residual (for example at the beginning of a time step),
340 // we may be in the process of counting invalid solution warnings, so the call to
341 // acceptInvalidSolution() would fail due to lack of parallel synchronization
342 // TODO: think of a better solution
344 {
345 mooseWarning("The solution is not converged due to the solution being invalid.");
346 return false;
347 }
348 return _nl_implicit_sys.nonlinear_solver->converged;
349}
350
351void
352NonlinearSystem::attachPreconditioner(Preconditioner<Number> * preconditioner)
353{
354 nonlinearSolver()->attach_preconditioner(preconditioner);
355}
356
357void
362
363void
368
369SNES
371{
374
375 if (petsc_solver)
376 {
377 const char * snes_prefix = nullptr;
378 std::string snes_prefix_str;
379 if (system().prefix_with_name())
380 {
381 snes_prefix_str = system().prefix();
382 snes_prefix = snes_prefix_str.c_str();
383 }
384 return petsc_solver->snes(snes_prefix);
385 }
386 else
387 mooseError("It is not a petsc nonlinear solver");
388}
389
390void
392{
395 "Evaluting the residual and Jacobian together does not make sense for a JFNK solve type in "
396 "which only function evaluations are required, e.g. there is no need to form a matrix");
397
398 nonlinearSolver()->residual_object = nullptr;
399 nonlinearSolver()->jacobian = nullptr;
400 nonlinearSolver()->residual_and_jacobian_object = &_resid_and_jac_functor;
401}
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:36
const ExecFlagType EXEC_LINEAR
Definition Moose.C:32
const ExecFlagType EXEC_NONLINEAR
Definition Moose.C:34
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:617
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.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
SolutionInvalidity & solutionInvalidity()
Get the SolutionInvalidity for this app.
Definition MooseApp.h:185
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
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
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
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)
PetscErrorCode libmesh_petsc_snes_fd_residual(SNES, Vec x, Vec r, void *ctx)