Smith  0.1
Smith is an implicit thermal structural mechanics simulation code.
nonlinear_convergence.cpp
1 // Copyright (c) Lawrence Livermore National Security, LLC and
2 // other Smith Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
7 #include "smith/numerics/nonlinear_convergence.hpp"
8 
9 #include <algorithm>
10 #include <cmath>
11 
12 #include "axom/fmt.hpp"
13 #include "axom/slic.hpp"
14 
15 namespace smith {
16 
17 namespace {
18 
19 double residualNorm(const mfem::Vector& residual, MPI_Comm comm)
20 {
21 #ifdef MFEM_USE_MPI
22  return mfem::ParNormlp(residual, 2.0, comm);
23 #else
24  static_cast<void>(comm);
25  return residual.Norml2();
26 #endif
27 }
28 
29 } // namespace
30 
32 
33 std::vector<double> computeResidualBlockNorms(const std::vector<mfem::Vector>& residuals, MPI_Comm comm)
34 {
35  std::vector<double> block_norms(residuals.size(), 0.0);
36  for (size_t i = 0; i < residuals.size(); ++i) {
37  block_norms[i] = residualNorm(residuals[i], comm);
38  }
39  return block_norms;
40 }
41 
42 ConvergenceStatus evaluateResidualConvergence(double tolerance_multiplier, double abs_tol, double rel_tol,
43  const std::vector<double>& block_norms,
45 {
46  ConvergenceStatus status;
47  status.block_norms = block_norms;
48 
49  double global_norm_squared = 0.0;
50  for (double block_norm : block_norms) {
51  global_norm_squared += block_norm * block_norm;
52  }
53 
54  status.global_norm = std::sqrt(global_norm_squared);
55  if (context.initial_global_norm < 0.0) {
56  context.initial_global_norm = status.global_norm;
57  }
58  status.global_goal = std::max(abs_tol, rel_tol * context.initial_global_norm);
59  status.global_converged = status.global_norm <= tolerance_multiplier * status.global_goal;
60  status.converged = status.global_converged;
61  return status;
62 }
63 
64 EquationSolverConvergenceManager::EquationSolverConvergenceManager(MPI_Comm comm, double abs_tol, double rel_tol)
65  : comm_(comm), abs_tol_(abs_tol), rel_tol_(rel_tol)
66 {
67 }
68 
69 void EquationSolverConvergenceManager::reset() const { context_.reset(); }
70 
71 void EquationSolverConvergenceManager::setTolerances(double abs_tol, double rel_tol) const
72 {
73  abs_tol_ = abs_tol;
74  rel_tol_ = rel_tol;
75 }
76 
78  const mfem::Vector& residual) const
79 {
80  return evaluateResidualConvergence(tolerance_multiplier, abs_tol_, rel_tol_, {residualNorm(residual, comm_)},
81  context_);
82 }
83 
84 } // namespace smith
void reset() const
Reset stored initial residual norms.
ConvergenceStatus evaluate(double tolerance_multiplier, const mfem::Vector &residual) const
Evaluate convergence for the current monolithic residual vector.
void setTolerances(double abs_tol, double rel_tol) const
Set scalar tolerances.
EquationSolverConvergenceManager(MPI_Comm comm, double abs_tol, double rel_tol)
Construct a convergence manager for one nonlinear solver.
Accelerator functionality.
Definition: smith.cpp:36
SMITH_HOST_DEVICE auto sqrt(dual< gradient_type > x)
implementation of square root for dual numbers
Definition: dual.hpp:308
SMITH_HOST_DEVICE auto max(dual< gradient_type > a, double b)
Implementation of max for dual numbers.
Definition: dual.hpp:229
std::vector< double > computeResidualBlockNorms(const std::vector< mfem::Vector > &residuals, MPI_Comm comm)
Compute one L2 norm per residual block.
ConvergenceStatus evaluateResidualConvergence(double tolerance_multiplier, double abs_tol, double rel_tol, const std::vector< double > &block_norms, NonlinearConvergenceContext &context)
Evaluate scalar nonlinear residual convergence.
Detailed status from evaluating nonlinear residual convergence.
double global_norm
Current scalar global residual norm.
bool global_converged
True when the scalar global residual criterion passes.
bool converged
True when the scalar global residual criterion passes.
std::vector< double > block_norms
Residual norms used to form the scalar global norm.
double global_goal
Scalar convergence threshold used for the global check.
Stores initial residual norms used for relative nonlinear convergence checks.
void reset()
Clear all stored initial norms for a new solve. The next convergence evaluation seeds a fresh relativ...
double initial_global_norm
Initial scalar global residual norm for the current solve.