MAST3
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
nonlinear_solver.hpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2020 Manav Bhatia and MAST authors
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #ifndef __mast_eigen_nonlinear_solver_h__
21 #define __mast_eigen_nonlinear_solver_h__
22 
23 // C++ includes
24 #include <iomanip>
25 
26 // MAST includes
28 #include <mast/base/exceptions.hpp>
30 
31 // PETSc includes
32 #include <petscmat.h>
33 
34 
35 namespace MAST {
36 namespace Solvers {
37 namespace EigenWrapper {
38 
39 template <typename ScalarType,
40  typename LinearSolverType,
41  typename FuncType>
43 
44 public:
45 
46  using scalar_t = ScalarType;
47  using vector_t = Eigen::Matrix<scalar_t, Eigen::Dynamic, 1>;
48  using matrix_t = typename FuncType::matrix_t;
49 
51  "Scalar type of function and nonlinear solver must be same");
53  "Vector type of function and nonlinear solver must be same");
54 
55 
56  real_t tol;
59 
61  tol (1.e-6),
62  rtol (1.e-6),
63  max_iter (20),
64  _func (nullptr) {
65 
66  }
67 
68 
69  virtual ~NonlinearSolver() {
70 
71  }
72 
79  inline void solve(FuncType &func,
80  vector_t &x) {
81 
82 
83  vector_t
84  res,
85  x0,
86  dx;
87 
88  matrix_t
89  jac;
90 
91  func.init_vector(res);
92  func.init_vector(x0);
93  func.init_vector(dx);
94  func.init_matrix(jac);
95 
96  func.residual(x, res);
97 
98  bool
99  if_cont = true;
100 
101  real_t
102  res_l2 = 0.,
103  res0_l2 = 0.,
104  dx_l2 = 0.;
105 
106  uint_t
107  iter = 0;
108 
109  res0_l2 = res_l2 = MAST::Numerics::Utility::real_norm(res);
110 
111  std::cout
112  << " Iter: " << std::setw(5) << iter
113  << " : || res ||_2 = "
114  << std::setw(15) << res_l2;
115 
116  while (if_cont) {
117 
118  func.jacobian(x, jac);
119 
120  dx = LinearSolverType(jac).solve(res);
121 
123 
124  // output
125  std::cout
126  << " : || dx ||_2 = "
127  << std::setw(15) << dx_l2 << std::endl;
128 
129  // x = x + dx
130  x -= dx;
131 
132  // copy solution to another vector
133  x0 = x;
134  iter++;
135 
136  // new residual
137  func.residual(x, res);
138 
139  // check for convergence
141 
142  std::cout
143  << " Iter: " << std::setw(5) << iter
144  << " : || res ||_2 = "
145  << std::setw(15) << res_l2;
146 
147  if (res_l2/res0_l2 < rtol) {
148 
149  if_cont = false;
150  std::cout
151  << " Terminating due to residual norm relative convergence"
152  << std::endl;
153  }
154  if (res_l2 < tol) {
155 
156  if_cont = false;
157  std::cout
158  << " Terminating due to residual norm convergence"
159  << std::endl;
160  }
161  if (dx_l2 < tol) {
162 
163  if_cont = false;
164  std::cout
165  << " Terminating due to step norm convergence"
166  << std::endl;
167  }
168  if (iter >= max_iter) {
169 
170  if_cont = false;
171  std::cout
172  << " Terminating due to maximum iterations"
173  << std::endl;
174  }
175  }
176  }
177 
178 
179 private:
180 
181  FuncType *_func;
182  std::string _nm;
183 };
184 
185 } // EigenWrapper
186 } // Solvers
187 } // MAST
188 
189 #endif // __mast_eigen_nonlinear_solver_h__
std::enable_if< std::is_same< typename Eigen::internal::traits< VecType >::Scalar, real_t >::value, real_t >::type real_norm(const VecType &v)
Definition: utility.hpp:63
std::enable_if< Dim< 3, ScalarType >::typesource_load_multiplier(const SourceLoadFieldType *f, const SectionAreaType *s, ContextType &c) { Assert0(f, "Invalid pointer");Assert0(s, "Invalid pointer");return f-> value(c) *s -> value(c)
Eigen::Matrix< scalar_t, Eigen::Dynamic, 1 > vector_t
void solve(FuncType &func, vector_t &x)
initialize the solver for function object func that provides the residual and jacobian evaluation...
unsigned int uint_t
double real_t