17#include <spdlog/fmt/bundled/core.h>
22struct fmt::formatter<SNESConvergedReason>
24 constexpr auto parse(format_parse_context& ctx) {
return ctx.end(); }
26 template <
typename FormatContext>
27 auto format(SNESConvergedReason
const reason, FormatContext& ctx)
31 return fmt::format_to(ctx.out(),
"DIVERGED: {}",
32 SNESConvergedReasons[-reason]);
34 return fmt::format_to(ctx.out(),
"CONVERGED: {}",
35 SNESConvergedReasons[reason]);
45 std::vector<GlobalVector*>&
x;
46 std::vector<GlobalVector*>
const&
x_prev;
55 auto context =
static_cast<PetscContext*
>(petsc_context);
57 DBUG(
"PETScNonlinearSolver: residual callback called.");
59 VecCopy(x, context->x[context->process_id]->getRawVector());
63 time_assembly.
start();
64 context->system->assemble(context->x, context->x_prev, context->process_id);
66 INFO(
"[time] Assembly took {} s.", time_assembly.
elapsed());
67 context->system->getResidual(*context->x[context->process_id],
68 *context->x_prev[context->process_id],
70 context->r->finalizeAssembly();
71 context->J->finalizeAssembly();
73 context->system->getJacobian(*context->J);
74 context->system->applyKnownSolutionsNewton(
75 *context->J, *context->r, *context->x[context->process_id]);
77 VecCopy(context->r->getRawVector(), petsc_r);
83 Mat ,
void* petsc_context)
85 DBUG(
"PETScNonlinearSolver: jacobian callback called.");
89 auto context =
static_cast<PetscContext*
>(petsc_context);
90 MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY);
91 MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY);
92 MatCopy(context->J->getRawMatrix(), J, DIFFERENT_NONZERO_PATTERN);
106 prefix = prefix +
"_";
114 PetscReal atol, rtol, stol;
116 SNESGetTolerances(
_snes_solver, &atol, &rtol, &stol,
nullptr, &maxf);
117 SNESSetTolerances(
_snes_solver, atol, rtol, stol, maxiter, maxf);
121 PetscOptionsView(
nullptr, PETSC_VIEWER_STDOUT_WORLD);
139 std::vector<GlobalVector*>
const& ,
140 std::vector<GlobalVector*>
const& ,
int const )
148 "Non-equilibrium initial residuum is not implemented for the "
149 "PETScNonlinearSolver.");
153 std::vector<GlobalVector*>& x,
154 std::vector<GlobalVector*>
const& x_prev,
157 std::vector<GlobalVector*>
const&)>
const& ,
158 int const process_id)
160 DBUG(
"PETScNonlinearSolver: solve()");
161 using TimeDiscretizedSystem =
167 DBUG(
"PETScNonlinearSolver: create vectors");
170 system->getMatrixSpecifications(process_id),
_jacobian_id);
172 system->getMatrixSpecifications(process_id),
_residual_id);
179 double time_dirichlet = 0.0;
181 timer_dirichlet.
start();
182 system->computeKnownSolutions(*x[process_id], process_id);
183 system->applyKnownSolutions(*x[process_id]);
184 time_dirichlet += timer_dirichlet.
elapsed();
185 INFO(
"[time] Applying Dirichlet BCs took {} s.", time_dirichlet);
190 system->getMatrixSpecifications(process_id),
_petsc_x_id);
193 PetscContext petsc_context{
_equation_system, x, x_prev, &r, &J, process_id};
195 DBUG(
"PETScNonlinearSolver: set function");
196 SNESSetFunction(
_snes_solver, r_snes.getRawVector(), updateResidual,
199 DBUG(
"PETScNonlinearSolver: set jacobian");
201 SNESSetJacobian(
_snes_solver, J_snes.getRawMatrix(), J_snes.getRawMatrix(),
202 updateJacobian, &petsc_context);
204 std::unique_ptr<GlobalVector> xl =
nullptr;
205 std::unique_ptr<GlobalVector> xu =
nullptr;
209 if ((std::strcmp(snes_type, SNESVINEWTONRSLS) == 0) ||
210 (std::strcmp(snes_type, SNESVINEWTONSSLS) == 0))
213 DBUG(
"PETScNonlinearSolver: set constraints");
215 system->getMatrixSpecifications(process_id));
217 system->getMatrixSpecifications(process_id));
219 system->updateConstraints(*xl, *xu, process_id);
223 SNESVISetVariableBounds(
_snes_solver, xl->getRawVector(),
227 DBUG(
"PETScNonlinearSolver: call SNESSolve");
228 SNESSolve(
_snes_solver,
nullptr, x_snes.getRawVector());
230 SNESConvergedReason reason = SNES_CONVERGED_ITERATING;
232 INFO(
"PETSsSNES convergence reason {}.", reason);
236 INFO(
"PETScSNES used {} iterations.", iterations);
247 return {reason >= 0, iterations};
void INFO(fmt::format_string< Args... > fmt, Args &&... args)
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition of the RunTime class.
double elapsed() const
Get the elapsed time in seconds.
void start()
Start the timer.
Global vector based on Eigen vector.
virtual void releaseMatrix(GlobalMatrix const &A)=0
virtual GlobalMatrix & getMatrix(std::size_t &id)=0
Get an uninitialized matrix with the given id.
std::size_t _petsc_residual_id
ConvergenceCriterion * _convergence_criterion
NonlinearSolverStatus solve(std::vector< GlobalVector * > &x, std::vector< GlobalVector * > const &x_prev, std::function< void(int, std::vector< GlobalVector * > const &)> const &postIterationCallback, int const process_id) override
std::size_t _petsc_jacobian_id
System * _equation_system
void setEquationSystem(System &eq, ConvergenceCriterion &conv_crit)
Set the nonlinear equation system that will be solved.
PETScNonlinearSolver(GlobalLinearSolver &linear_solver, int maxiter, std::string prefix)
bool _compensate_non_equilibrium_initial_residuum
std::size_t _jacobian_id
ID of the Jacobian matrix.
void compensateNonEquilibriumInitialResiduum(bool const value)
std::size_t _residual_id
ID of the residual vector.
void calculateNonEquilibriumInitialResiduum(std::vector< GlobalVector * > const &x, std::vector< GlobalVector * > const &x_prev, int const process_id) override
virtual GlobalVector & getVector(std::size_t &id)=0
Get an uninitialized vector with the given id.
virtual void releaseVector(GlobalVector const &x)=0
@ FirstOrderImplicitQuasilinear
void copy(PETScVector const &x, PETScVector &y)
void finalizeVectorAssembly(VEC_T &)
General function to finalize the vector assembly.
PetscErrorCode updateResidual(SNES, Vec x, Vec petsc_r, void *petsc_context)
PetscErrorCode updateJacobian(SNES, Vec, Mat J, Mat, void *petsc_context)
static NUMLIB_EXPORT MatrixProvider & provider
static NUMLIB_EXPORT VectorProvider & provider
Status of the non-linear solver.
std::vector< GlobalVector * > & x
std::vector< GlobalVector * > const & x_prev