89 std::vector<GlobalVector*>
const& x,
90 std::vector<GlobalVector*>
const& x_prev,
int const process_id)
92 if (!_compensate_non_equilibrium_initial_residuum)
97 INFO(
"Calculate non-equilibrium initial residuum.");
101 _equation_system->assemble(x, x_prev, process_id);
102 _equation_system->getA(A);
103 _equation_system->getRhs(*x_prev[process_id], rhs);
113 const auto selected_global_indices =
114 _equation_system->getIndicesOfResiduumWithoutInitialCompensation();
116 std::vector<double> zero_entries(selected_global_indices.size(), 0.0);
117 _r_neq->set(selected_global_indices, zero_entries);
126 std::vector<GlobalVector*>& x,
127 std::vector<GlobalVector*>
const& x_prev,
128 std::function<
void(
int, std::vector<GlobalVector*>
const&)>
const&
129 postIterationCallback,
130 int const process_id)
133 auto& sys = *_equation_system;
138 std::vector<GlobalVector*> x_new{x};
143 bool error_norms_met =
false;
145 _convergence_criterion->preFirstIteration();
148 for (; iteration <= _maxiter; ++iteration, _convergence_criterion->reset())
151 double time_dirichlet = 0.0;
154 time_iteration.
start();
156 timer_dirichlet.
start();
157 auto& x_new_process = *x_new[process_id];
159 sys.computeKnownSolutions(x_new_process, process_id);
160 sys.applyKnownSolutions(x_new_process);
161 time_dirichlet += timer_dirichlet.
elapsed();
163 sys.preIteration(iteration, x_new_process);
166 time_assembly.
start();
167 sys.assemble(x_new, x_prev, process_id);
169 sys.getRhs(*x_prev[process_id], rhs);
172 if (sys.requiresNormalization())
173 sys.getAandRhsNormalized(A, rhs);
175 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
178 if (_r_neq !=
nullptr)
183 timer_dirichlet.
start();
184 sys.applyKnownSolutionsPicard(A, rhs, x_new_process);
185 time_dirichlet += timer_dirichlet.
elapsed();
186 INFO(
"[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
188 if (!sys.isLinear() && _convergence_criterion->hasResidualCheck())
193 _convergence_criterion->checkResidual(res);
196 bool iteration_succeeded =
198 sys.linearSolverNeedsToCompute());
200 if (iteration_succeeded)
202 if (postIterationCallback)
204 postIterationCallback(iteration, x_new);
207 switch (sys.postIteration(x_new_process))
214 ERR(
"Picard: The postIteration() hook reported a "
215 "non-recoverable error.");
216 iteration_succeeded =
false;
224 "Picard: The postIteration() hook decided that this "
225 "iteration has to be repeated.");
233 if (!iteration_succeeded)
236 error_norms_met =
false;
242 error_norms_met =
true;
246 if (_convergence_criterion->hasDeltaXCheck())
251 _convergence_criterion->checkDeltaX(minus_delta_x,
255 error_norms_met = _convergence_criterion->isSatisfied();
261 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
271 if (iteration >= _maxiter)
277 if (iteration > _maxiter)
279 ERR(
"Picard: Could not solve the given nonlinear system within {:d} "
288 return {error_norms_met, iteration};
293 std::vector<GlobalVector*>
const& x,
294 std::vector<GlobalVector*>
const& x_prev,
int const process_id)
296 if (!_compensate_non_equilibrium_initial_residuum)
301 INFO(
"Calculate non-equilibrium initial residuum.");
303 _equation_system->assemble(x, x_prev, process_id);
305 _equation_system->getResidual(*x[process_id], *x_prev[process_id], *_r_neq);
310 const auto selected_global_indices =
311 _equation_system->getIndicesOfResiduumWithoutInitialCompensation();
312 std::vector<double> zero_entries(selected_global_indices.size(), 0.0);
314 _r_neq->set(selected_global_indices, zero_entries);
320 std::vector<GlobalVector*>& x,
321 std::vector<GlobalVector*>
const& x_prev,
322 std::function<
void(
int, std::vector<GlobalVector*>
const&)>
const&
323 postIterationCallback,
324 int const process_id)
327 auto& sys = *_equation_system;
330 auto& minus_delta_x =
334 bool error_norms_met =
false;
340 _convergence_criterion->preFirstIteration();
343 for (; iteration <= _maxiter; ++iteration, _convergence_criterion->reset())
346 double time_dirichlet = 0.0;
349 time_iteration.
start();
351 timer_dirichlet.
start();
352 sys.computeKnownSolutions(*x[process_id], process_id);
353 time_dirichlet += timer_dirichlet.
elapsed();
355 sys.preIteration(iteration, *x[process_id]);
358 time_assembly.
start();
361 sys.assemble(x, x_prev, process_id);
365 ERR(
"Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
367 error_norms_met =
false;
368 iteration = _maxiter;
371 sys.getResidual(*x[process_id], *x_prev[process_id], res);
373 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
376 if (_r_neq !=
nullptr)
379 minus_delta_x.setZero();
381 timer_dirichlet.
start();
382 sys.applyKnownSolutionsNewton(J, res, *x[process_id], minus_delta_x);
383 time_dirichlet += timer_dirichlet.
elapsed();
384 INFO(
"[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
386 if (!sys.isLinear() && _convergence_criterion->hasResidualCheck())
388 _convergence_criterion->checkResidual(res);
392 time_linear_solver.
start();
393 bool iteration_succeeded = _linear_solver.solve(J, res, minus_delta_x);
394 INFO(
"[time] Linear solver took {:g} s.", time_linear_solver.
elapsed());
396 if (!iteration_succeeded)
398 ERR(
"Newton: The linear solver failed.");
407 std::vector<GlobalVector*> x_new{x};
410 *x[process_id], _x_new_id);
411 LinAlg::axpy(*x_new[process_id], -_damping, minus_delta_x);
413 if (postIterationCallback)
415 postIterationCallback(iteration, x_new);
418 switch (sys.postIteration(*x_new[process_id]))
423 ERR(
"Newton: The postIteration() hook reported a "
424 "non-recoverable error.");
425 iteration_succeeded =
false;
429 "Newton: The postIteration() hook decided that this "
430 "iteration has to be repeated.");
443 if (!iteration_succeeded)
446 error_norms_met =
false;
452 error_norms_met =
true;
456 if (_convergence_criterion->hasDeltaXCheck())
459 _convergence_criterion->checkDeltaX(minus_delta_x,
463 error_norms_met = _convergence_criterion->isSatisfied();
466 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
476 if (iteration >= _maxiter)
482 if (iteration > _maxiter)
484 ERR(
"Newton: Could not solve the given nonlinear system within {:d} "
493 return {error_norms_met, iteration};
505 if (type ==
"Picard")
509 return std::make_pair(
510 std::make_unique<ConcreteNLS>(linear_solver, max_iter), tag);
512 if (type ==
"Newton")
519 "The damping factor for the Newon method must be positive, got "
525 return std::make_pair(
526 std::make_unique<ConcreteNLS>(linear_solver, max_iter, damping),
530 if (boost::iequals(type,
"PETScSNES"))
537 return std::make_pair(std::make_unique<ConcreteNLS>(
538 linear_solver, max_iter, std::move(prefix)),
543 OGS_FATAL(
"Unsupported nonlinear solver type '{:s}'.", type.c_str());