Assemble and solve the equation system.
338{
341
343 auto& minus_delta_x =
346
347 bool error_norms_met = false;
348
349
350
352
354
355 int iteration = 1;
356#if !defined(USE_PETSC) && !defined(USE_LIS)
357 int next_iteration_inv_jacobian_recompute = 1;
358#endif
360 {
362 double time_dirichlet = 0.0;
363
365 INFO(
"Iteration #{:d} started.", iteration);
366 time_iteration.
start();
367
368 timer_dirichlet.
start();
369 sys.computeKnownSolutions(*x[process_id], process_id);
370 time_dirichlet += timer_dirichlet.
elapsed();
371
372 sys.preIteration(iteration, *x[process_id]);
373
375 time_assembly.
start();
376 bool mpi_rank_assembly_ok = true;
377 try
378 {
379 sys.assemble(x, x_prev, process_id);
380 }
381 catch (AssemblyException const& e)
382 {
383 ERR(
"Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
384 e.what());
385 error_norms_met = false;
387 mpi_rank_assembly_ok = false;
388 }
390 {
391 break;
392 }
393 sys.getResidual(*x[process_id], *x_prev[process_id], res);
394 sys.getJacobian(J);
395 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
396
397
400
401 minus_delta_x.setZero();
402
403 timer_dirichlet.
start();
404 sys.applyKnownSolutionsNewton(J, res, *x[process_id], minus_delta_x);
405 time_dirichlet += timer_dirichlet.
elapsed();
406 INFO(
"[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
407
409 {
411 }
412
414 time_linear_solver.
start();
415#if !defined(USE_PETSC) && !defined(USE_LIS)
417 if (iteration == next_iteration_inv_jacobian_recompute)
418 {
419 linear_solver_behaviour =
421 next_iteration_inv_jacobian_recompute =
423 }
425 {
426 ERR(
"Newton: The linear solver failed in the compute() step.");
427 }
429#else
431#endif
432 INFO(
"[time] Linear solver took {:g} s.", time_linear_solver.
elapsed());
433
434 if (!iteration_succeeded)
435 {
436 ERR(
"Newton: The linear solver failed.");
437 }
438 else
439 {
440
441
442
443
444
445 std::vector<GlobalVector*> x_new{x};
446 x_new[process_id] =
451 {
453 minus_delta_x, *x[process_id],
_damping);
454 }
456 {
457 damping =
458 damping +
459 (1 - damping) *
461 }
462 LinAlg::axpy(*x_new[process_id], -damping, minus_delta_x);
463
464 if (postIterationCallback)
465 {
466 postIterationCallback(iteration, error_norms_met, x_new);
467 }
468
469 switch (sys.postIteration(*x_new[process_id]))
470 {
472 break;
474 ERR(
"Newton: The postIteration() hook reported a "
475 "non-recoverable error.");
476 iteration_succeeded = false;
477 break;
480 "Newton: The postIteration() hook decided that this "
481 "iteration has to be repeated.");
482
484 *x_new[process_id]);
485 continue;
486 }
487
489 *x[process_id]);
491 *x_new[process_id]);
492 }
493
494 if (!iteration_succeeded)
495 {
496
497 error_norms_met = false;
498 break;
499 }
500
501 if (sys.isLinear())
502 {
503 error_norms_met = true;
504 }
505 else
506 {
508 {
509
511 *x[process_id]);
512 }
513
515 }
516
517 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
519
520 if (error_norms_met)
521 {
522 break;
523 }
524
525
526
528 {
529 break;
530 }
531 }
532
534 {
535 ERR(
"Newton: Could not solve the given nonlinear system within {:d} "
536 "iterations",
538 }
539
543
544 return {error_norms_met, iteration};
545}
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
double elapsed() const
Get the elapsed time in seconds.
void start()
Start the timer.
bool solve(EigenMatrix &A, EigenVector &b, EigenVector &x)
virtual double getDampingFactor(GlobalVector const &minus_delta_x, GlobalVector const &x, double damping_orig)=0
virtual void preFirstIteration()
virtual void checkResidual(GlobalVector const &residual)=0
Check if the residual satisfies the convergence criterion.
virtual bool hasResidualCheck() const =0
virtual bool isSatisfied() const
Tell if the convergence criterion is satisfied.
virtual void checkDeltaX(GlobalVector const &minus_delta_x, GlobalVector const &x)=0
virtual bool hasDeltaXCheck() const =0
virtual bool hasNonNegativeDamping() const =0
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 _J_id
ID of the Jacobian matrix.
std::size_t _x_new_id
ID of the vector storing .
std::size_t _res_id
ID of the residual vector.
std::size_t _minus_delta_x_id
ID of the vector.
static bool anyOf(bool const val, Mpi const &mpi=Mpi{OGS_COMM_WORLD})
void copy(PETScVector const &x, PETScVector &y)
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
static NUMLIB_EXPORT MatrixProvider & provider