Assemble and solve the equation system.
336{
339
341 auto& minus_delta_x =
344
345 bool error_norms_met = false;
346
347
348
350
352
353 int iteration = 1;
354#if !defined(USE_PETSC) && !defined(USE_LIS)
355 int next_iteration_inv_jacobian_recompute = 1;
356#endif
358 {
360 double time_dirichlet = 0.0;
361
363 time_iteration.
start();
364
365 timer_dirichlet.
start();
366 sys.computeKnownSolutions(*x[process_id], process_id);
367 time_dirichlet += timer_dirichlet.
elapsed();
368
369 sys.preIteration(iteration, *x[process_id]);
370
372 time_assembly.
start();
373 bool mpi_rank_assembly_ok = true;
374 try
375 {
376 sys.assemble(x, x_prev, process_id);
377 }
378 catch (AssemblyException const& e)
379 {
380 ERR(
"Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
381 e.what());
382 error_norms_met = false;
384 mpi_rank_assembly_ok = false;
385 }
387 {
388 break;
389 }
390 sys.getResidual(*x[process_id], *x_prev[process_id], res);
391 sys.getJacobian(J);
392 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
393
394
397
398 minus_delta_x.setZero();
399
400 timer_dirichlet.
start();
401 sys.applyKnownSolutionsNewton(J, res, *x[process_id], minus_delta_x);
402 time_dirichlet += timer_dirichlet.
elapsed();
403 INFO(
"[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
404
406 {
408 }
409
411 time_linear_solver.
start();
412#if !defined(USE_PETSC) && !defined(USE_LIS)
414 if (iteration == next_iteration_inv_jacobian_recompute)
415 {
416 linear_solver_behaviour =
418 next_iteration_inv_jacobian_recompute =
420 }
422 {
423 ERR(
"Newton: The linear solver failed in the compute() step.");
424 }
426#else
428#endif
429 INFO(
"[time] Linear solver took {:g} s.", time_linear_solver.
elapsed());
430
431 if (!iteration_succeeded)
432 {
433 ERR(
"Newton: The linear solver failed.");
434 }
435 else
436 {
437
438
439
440
441
442 std::vector<GlobalVector*> x_new{x};
443 x_new[process_id] =
448 {
450 minus_delta_x, *x[process_id],
_damping);
451 }
452 LinAlg::axpy(*x_new[process_id], -damping, minus_delta_x);
453
454 if (postIterationCallback)
455 {
456 postIterationCallback(iteration, error_norms_met, x_new);
457 }
458
459 switch (sys.postIteration(*x_new[process_id]))
460 {
462 break;
464 ERR(
"Newton: The postIteration() hook reported a "
465 "non-recoverable error.");
466 iteration_succeeded = false;
467 break;
470 "Newton: The postIteration() hook decided that this "
471 "iteration has to be repeated.");
472
474 *x_new[process_id]);
475 continue;
476 }
477
479 *x[process_id]);
481 *x_new[process_id]);
482 }
483
484 if (!iteration_succeeded)
485 {
486
487 error_norms_met = false;
488 break;
489 }
490
491 if (sys.isLinear())
492 {
493 error_norms_met = true;
494 }
495 else
496 {
498 {
499
501 *x[process_id]);
502 }
503
505 }
506
507 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
509
510 if (error_norms_met)
511 {
512 break;
513 }
514
515
516
518 {
519 break;
520 }
521 }
522
524 {
525 ERR(
"Newton: Could not solve the given nonlinear system within {:d} "
526 "iterations",
528 }
529
533
534 return {error_norms_met, iteration};
535}
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{MPI_COMM_WORLD})
void copy(PETScVector const &x, PETScVector &y)
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
static NUMLIB_EXPORT MatrixProvider & provider