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 sys.applyKnownSolutions(*x[process_id]);
349 time_dirichlet += timer_dirichlet.
elapsed();
350
351 sys.preIteration(iteration, *x[process_id]);
352
354 time_assembly.
start();
355 try
356 {
357 sys.assemble(x, x_prev, process_id);
358 }
359 catch (AssemblyException const& e)
360 {
361 ERR(
"Abort nonlinear iteration. Repeating timestep. Reason: {:s}",
362 e.what());
363 error_norms_met = false;
365 break;
366 }
367 sys.getResidual(*x[process_id], *x_prev[process_id], res);
368 sys.getJacobian(J);
369 INFO(
"[time] Assembly took {:g} s.", time_assembly.
elapsed());
370
371
374
375 minus_delta_x.setZero();
376
377 timer_dirichlet.
start();
378 sys.applyKnownSolutionsNewton(J, res, minus_delta_x);
379 time_dirichlet += timer_dirichlet.
elapsed();
380 INFO(
"[time] Applying Dirichlet BCs took {:g} s.", time_dirichlet);
381
383 {
385 }
386
388 time_linear_solver.
start();
390 INFO(
"[time] Linear solver took {:g} s.", time_linear_solver.
elapsed());
391
392 if (!iteration_succeeded)
393 {
394 ERR(
"Newton: The linear solver failed.");
395 }
396 else
397 {
398
399
400
401
402
403 std::vector<GlobalVector*> x_new{x};
404 x_new[process_id] =
408
409 if (postIterationCallback)
410 {
411 postIterationCallback(iteration, x_new);
412 }
413
414 switch (sys.postIteration(*x_new[process_id]))
415 {
417 break;
419 ERR(
"Newton: The postIteration() hook reported a "
420 "non-recoverable error.");
421 iteration_succeeded = false;
422 break;
425 "Newton: The postIteration() hook decided that this "
426 "iteration has to be repeated.");
427
429 *x_new[process_id]);
430 continue;
431 }
432
434 *x[process_id]);
436 *x_new[process_id]);
437 }
438
439 if (!iteration_succeeded)
440 {
441
442 error_norms_met = false;
443 break;
444 }
445
446 if (sys.isLinear())
447 {
448 error_norms_met = true;
449 }
450 else
451 {
453 {
454
456 *x[process_id]);
457 }
458
460 }
461
462 INFO(
"[time] Iteration #{:d} took {:g} s.", iteration,
464
465 if (error_norms_met)
466 {
467 break;
468 }
469
470
471
473 {
474 break;
475 }
476 }
477
479 {
480 ERR(
"Newton: Could not solve the given nonlinear system within {:d} "
481 "iterations",
483 }
484
488
489 return {error_norms_met, iteration};
490}
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