Assemble and solve the equation system.
325{
328
330 auto& minus_delta_x =
333
334 bool error_norms_met = false;
335
336
337
339
341
342 int iteration = 1;
344 {
346 double time_dirichlet = 0.0;
347
349 time_iteration.
start();
350
351 timer_dirichlet.
start();
352 sys.computeKnownSolutions(*x[process_id], process_id);
353 time_dirichlet += timer_dirichlet.
elapsed();
354
355 sys.preIteration(iteration, *x[process_id]);
356
358 time_assembly.
start();
359 try
360 {
361 sys.assemble(x, x_prev, process_id);
362 }
363 catch (AssemblyException const& e)
364 {
365 ERR(
"Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
366 e.what());
367 error_norms_met = false;
369 break;
370 }
371 sys.getResidual(*x[process_id], *x_prev[process_id], res);
372 sys.getJacobian(J);
373 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
374
375
378
379 minus_delta_x.setZero();
380
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);
385
387 {
389 }
390
392 time_linear_solver.
start();
394 INFO(
"[time] Linear solver took {:g} s.", time_linear_solver.
elapsed());
395
396 if (!iteration_succeeded)
397 {
398 ERR(
"Newton: The linear solver failed.");
399 }
400 else
401 {
402
403
404
405
406
407 std::vector<GlobalVector*> x_new{x};
408 x_new[process_id] =
412
413 if (postIterationCallback)
414 {
415 postIterationCallback(iteration, x_new);
416 }
417
418 switch (sys.postIteration(*x_new[process_id]))
419 {
421 break;
423 ERR(
"Newton: The postIteration() hook reported a "
424 "non-recoverable error.");
425 iteration_succeeded = false;
426 break;
429 "Newton: The postIteration() hook decided that this "
430 "iteration has to be repeated.");
431
433 *x_new[process_id]);
434 continue;
435 }
436
438 *x[process_id]);
440 *x_new[process_id]);
441 }
442
443 if (!iteration_succeeded)
444 {
445
446 error_norms_met = false;
447 break;
448 }
449
450 if (sys.isLinear())
451 {
452 error_norms_met = true;
453 }
454 else
455 {
457 {
458
460 *x[process_id]);
461 }
462
464 }
465
466 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
468
469 if (error_norms_met)
470 {
471 break;
472 }
473
474
475
477 {
478 break;
479 }
480 }
481
483 {
484 ERR(
"Newton: Could not solve the given nonlinear system within {:d} "
485 "iterations",
487 }
488
492
493 return {error_norms_met, iteration};
494}
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.
void copy(PETScVector const &x, PETScVector &y)
void axpy(PETScVector &y, PetscScalar const a, PETScVector const &x)
static NUMLIB_EXPORT MatrixProvider & provider