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;
355 {
357 double time_dirichlet = 0.0;
358
360 time_iteration.
start();
361
362 timer_dirichlet.
start();
363 sys.computeKnownSolutions(*x[process_id], process_id);
364 time_dirichlet += timer_dirichlet.
elapsed();
365
366 sys.preIteration(iteration, *x[process_id]);
367
369 time_assembly.
start();
370 int mpi_rank_assembly_ok = 1;
371 int mpi_all_assembly_ok = 0;
372 try
373 {
374 sys.assemble(x, x_prev, process_id);
375 }
376 catch (AssemblyException const& e)
377 {
378 ERR(
"Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
379 e.what());
380 error_norms_met = false;
382 mpi_rank_assembly_ok = 0;
383 }
385 if (mpi_all_assembly_ok == 0)
386 {
387 break;
388 }
389 sys.getResidual(*x[process_id], *x_prev[process_id], res);
390 sys.getJacobian(J);
391 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
392
393
396
397 minus_delta_x.setZero();
398
399 timer_dirichlet.
start();
400 sys.applyKnownSolutionsNewton(J, res, *x[process_id], minus_delta_x);
401 time_dirichlet += timer_dirichlet.
elapsed();
402 INFO(
"[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
403
405 {
407 }
408
410 time_linear_solver.
start();
412 INFO(
"[time] Linear solver took {:g} s.", time_linear_solver.
elapsed());
413
414 if (!iteration_succeeded)
415 {
416 ERR(
"Newton: The linear solver failed.");
417 }
418 else
419 {
420
421
422
423
424
425 std::vector<GlobalVector*> x_new{x};
426 x_new[process_id] =
430
431 if (postIterationCallback)
432 {
433 postIterationCallback(iteration, x_new);
434 }
435
436 switch (sys.postIteration(*x_new[process_id]))
437 {
439 break;
441 ERR(
"Newton: The postIteration() hook reported a "
442 "non-recoverable error.");
443 iteration_succeeded = false;
444 break;
447 "Newton: The postIteration() hook decided that this "
448 "iteration has to be repeated.");
449
451 *x_new[process_id]);
452 continue;
453 }
454
456 *x[process_id]);
458 *x_new[process_id]);
459 }
460
461 if (!iteration_succeeded)
462 {
463
464 error_norms_met = false;
465 break;
466 }
467
468 if (sys.isLinear())
469 {
470 error_norms_met = true;
471 }
472 else
473 {
475 {
476
478 *x[process_id]);
479 }
480
482 }
483
484 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
486
487 if (error_norms_met)
488 {
489 break;
490 }
491
492
493
495 {
496 break;
497 }
498 }
499
501 {
502 ERR(
"Newton: Could not solve the given nonlinear system within {:d} "
503 "iterations",
505 }
506
510
511 return {error_norms_met, iteration};
512}
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 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 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 int reduceMin(int const val)
void copy(PETScVector const &x, PETScVector &y)
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
static NUMLIB_EXPORT MatrixProvider & provider