Assemble and solve the equation system.
320{
323
325 auto& minus_delta_x =
328
329 bool error_norms_met = false;
330
331
332
334
336
337 int iteration = 1;
339 {
341 double time_dirichlet = 0.0;
342
344 time_iteration.
start();
345
346 timer_dirichlet.
start();
347 sys.computeKnownSolutions(*x[process_id], process_id);
348 time_dirichlet += timer_dirichlet.
elapsed();
349
350 sys.preIteration(iteration, *x[process_id]);
351
353 time_assembly.
start();
354 try
355 {
356 sys.assemble(x, x_prev, process_id);
357 }
358 catch (AssemblyException const& e)
359 {
360 ERR(
"Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
361 e.what());
362 error_norms_met = false;
364 break;
365 }
366 sys.getResidual(*x[process_id], *x_prev[process_id], res);
367 sys.getJacobian(J);
368 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
369
370
373
374 minus_delta_x.setZero();
375
376 timer_dirichlet.
start();
377 sys.applyKnownSolutionsNewton(J, res, *x[process_id], minus_delta_x);
378 time_dirichlet += timer_dirichlet.
elapsed();
379 INFO(
"[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
380
382 {
384 }
385
387 time_linear_solver.
start();
389 INFO(
"[time] Linear solver took {:g} s.", time_linear_solver.
elapsed());
390
391 if (!iteration_succeeded)
392 {
393 ERR(
"Newton: The linear solver failed.");
394 }
395 else
396 {
397
398
399
400
401
402 std::vector<GlobalVector*> x_new{x};
403 x_new[process_id] =
407
408 if (postIterationCallback)
409 {
410 postIterationCallback(iteration, x_new);
411 }
412
413 switch (sys.postIteration(*x_new[process_id]))
414 {
416 break;
418 ERR(
"Newton: The postIteration() hook reported a "
419 "non-recoverable error.");
420 iteration_succeeded = false;
421 break;
424 "Newton: The postIteration() hook decided that this "
425 "iteration has to be repeated.");
426
428 *x_new[process_id]);
429 continue;
430 }
431
433 *x[process_id]);
435 *x_new[process_id]);
436 }
437
438 if (!iteration_succeeded)
439 {
440
441 error_norms_met = false;
442 break;
443 }
444
445 if (sys.isLinear())
446 {
447 error_norms_met = true;
448 }
449 else
450 {
452 {
453
455 *x[process_id]);
456 }
457
459 }
460
461 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
463
464 if (error_norms_met)
465 {
466 break;
467 }
468
469
470
472 {
473 break;
474 }
475 }
476
478 {
479 ERR(
"Newton: Could not solve the given nonlinear system within {:d} "
480 "iterations",
482 }
483
487
488 return {error_norms_met, iteration};
489}
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