G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsStaticNewton.hpp
Go to the documentation of this file.
1 
14 #include <typeinfo>
15 #pragma once
16 
17 namespace gismo
18 {
19 
20 template <class T>
22 {
23  Base::defaultOptions();
24  m_options.setString("Solver","CGDiagonal"); // The CG solver is robust for membrane models, where zero-blocks in the matrix might occur.
25  m_options.addReal("Relaxation","Relaxation parameter",1);
26 };
27 
28 template <class T>
30 {
31  Base::getOptions();
32 
33  // if (m_solverType!=solver::LDLT && m_stabilityMethod==stabmethod::Determinant)
34  // {
35  // gsWarn<<"Determinant method cannot be used with solvers other than LDLT. Bifurcation method will be set to 'Eigenvalue'.\n";
36  // m_stabilityMethod = stabmethod::Eigenvalue;
37  // }
38 
39  m_relax = m_options.getReal("Relaxation");
40 };
41 
42 template <class T>
44 {
45  gsInfo<<"\t";
46  gsInfo<<std::setw(4)<<std::left<<"It.";
47  gsInfo<<std::setw(17)<<std::left<<"|R|";
48  gsInfo<<std::setw(17)<<std::left<<"|R|/|R0|";
49  gsInfo<<std::setw(17)<<std::left<<"|DU|";
50  gsInfo<<std::setw(17)<<std::left<<"|dU|";
51  gsInfo<<std::setw(17)<<std::left<<"|dU|/|DU|";
52  gsInfo<<std::setw(17)<<std::left<<"|dU|/|U+DU|";
53  gsInfo<<std::setw(17)<<std::left<<"log(Ri/R0):";
54  gsInfo<<std::setw(17)<<std::left<<"log(Ri+1/R0)";
55  gsInfo<<"\n";
56 }
57 
58 template <class T>
60 {
61  gsInfo<<"\t";
62  gsInfo<<std::setw(4)<<std::left<<k;
63  gsInfo<<std::setw(17)<<std::left<<m_residual;
64  gsInfo<<std::setw(17)<<std::left<<m_residual/m_residualIni;
65  gsInfo<<std::setw(17)<<std::left<<m_DeltaU.norm();
66  gsInfo<<std::setw(17)<<std::left<<m_relax * m_deltaU.norm();
67  gsInfo<<std::setw(17)<<std::left<<m_relax * m_deltaU.norm()/m_DeltaU.norm();
68  gsInfo<<std::setw(17)<<std::left<<m_relax * m_deltaU.norm()/(m_U+m_DeltaU).norm();
69  gsInfo<<std::setw(17)<<std::left<<math::log10(m_residualOld/m_residualIni);
70  gsInfo<<std::setw(17)<<std::left<<math::log10(m_residual/m_residualIni);
71  gsInfo<<"\n";
72 
73 }
74 
75 template <class T>
77 {
78  try
79  {
80  _solveLinear();
81  m_status = gsStatus::Success;
82  }
83  catch (int errorCode)
84  {
85  if (errorCode==1)
86  m_status = gsStatus::NotConverged;
87  else if (errorCode==2)
88  m_status = gsStatus::AssemblyError;
89  else if (errorCode==3)
90  m_status = gsStatus::SolverError;
91  else
92  m_status = gsStatus::OtherError;
93  }
94  catch (...)
95  {
96  m_status = gsStatus::OtherError;
97  }
98  return m_status;
99 };
100 
101 template <class T>
103 {
104  this->getOptions();
105  if (m_verbose==2)
106  {
107  gsInfo<<"Matrix: \n"<<m_linear.toDense()<<"\n";
108  gsInfo<<"Vector: \n"<<m_force<<"\n";
109  }
110  _factorizeMatrix( m_linear );
111  m_U = _solveSystem(m_force);
112  return m_U;
113 };
114 
115 template <class T>
117 {
118  try
119  {
120  _solveNonlinear();
121  m_status = gsStatus::Success;
122  }
123  catch (int errorCode)
124  {
125  if (errorCode==1)
126  m_status = gsStatus::NotConverged;
127  else if (errorCode==2)
128  m_status = gsStatus::AssemblyError;
129  else if (errorCode==3)
130  m_status = gsStatus::SolverError;
131  else
132  m_status = gsStatus::OtherError;
133  }
134  catch (...)
135  {
136  m_status = gsStatus::OtherError;
137  }
138  return m_status;
139 }
140 
141 
142 template <class T>
144 {
145  this->getOptions();
146  // m_start: true -> m_U given
147  // m_headstart: true -> m_DeltaU given
148 
149  if (m_DeltaU.norm()==0 && m_DeltaU.rows()==0)
150  {
151  m_deltaU = m_DeltaU = this->_solveLinear();
152  m_U.setZero(); // Needed because linear solve modifies m_U.
153  m_headstart = true; // due to this, the relative residual is based on the solution of the linear solve
154  }
155  _start();
156 
157  gsSparseMatrix<T> jacMat;
158 
159  if (m_verbose>0) { initOutput(); }
160 
161  for (m_numIterations = 0; m_numIterations != m_maxIterations; ++m_numIterations)
162  {
163  jacMat = this->_computeJacobian(m_U+m_DeltaU,m_deltaU);
164  if (m_verbose==2)
165  {
166  gsInfo<<"Matrix: \n"<<jacMat.toDense()<<"\n";
167  gsInfo<<"Vector: \n"<<m_R<<"\n";
168  }
169 
170  _factorizeMatrix(jacMat);
171  m_deltaU = _solveSystem(m_R); // this is the UPDATE
172  m_DeltaU += m_relax * m_deltaU;
173 
174  m_R = this->_computeResidual(m_U+m_DeltaU);
175  m_residual = m_R.norm();
176 
177  if (m_verbose>0) { stepOutput(m_numIterations); }
178 
179  m_residualOld = m_residual;
180 
181  if (m_relax * m_deltaU.norm()/m_DeltaU.norm() < m_tolU && m_residual/m_residualIni < m_tolF)
182  {
183  m_U+=m_DeltaU;
184  break;
185  }
186  else if (m_numIterations+1 == m_maxIterations)
187  {
188  m_U+=m_DeltaU;
189  gsInfo<<"Maximum iterations reached. Solution did not converge\n";
190  throw 1;
191  }
192  }
193  return m_U;
194 };
195 
196 template <class T>
198 {
199  gsVector<T> resVec;
200  if (!m_residualFun(U, resVec))
201  throw 2;
202  return resVec;
203 }
204 
205 template <class T>
206 gsSparseMatrix<T> gsStaticNewton<T>::_computeJacobian(const gsVector<T> & U, const gsVector<T> & deltaU)
207 {
208  // Compute Jacobian
209  gsSparseMatrix<T> m;
210  if (!m_dnonlinear(U,deltaU,m))
211  throw 2;
212  return m;
213 }
214 
215 template <class T>
217 {
218  m_solver->compute(jacMat);
219  if (m_solver->info()!=gsEigen::ComputationInfo::Success)
220  {
221  gsInfo<<"Solver error with code "<<m_solver->info()<<". See Eigen documentation on ComputationInfo \n"
222  <<gsEigen::ComputationInfo::Success<<": Success"<<"\n"
223  <<gsEigen::ComputationInfo::NumericalIssue<<": NumericalIssue"<<"\n"
224  <<gsEigen::ComputationInfo::NoConvergence<<": NoConvergence"<<"\n"
225  <<gsEigen::ComputationInfo::InvalidInput<<": InvalidInput"<<"\n";
226  throw 3;
227  }
228 }
229 
230 template <class T>
232 {
233  try
234  {
235  return m_solver->solve(F);
236  }
237  catch (...)
238  {
239  throw 3;
240  }
241 }
242 
243 template <class T>
245 {
246  m_dofs = m_force.rows();
247  // resets m_U, m_DeltaU, m_deltaU, m_R, m_L, m_DeltaL, m_deltaL and m_headstart
248  Base::reset();
249 }
250 
251 template <class T>
253 {
254  this->reset();
255  if( m_dnonlinear==nullptr || m_residualFun==nullptr)
256  m_NL=false;
257  else
258  m_NL = true;
259 
260  m_stabilityMethod = 0;
261  m_start = false;
262 
263  if (m_dofs==0)
264  gsWarn<<"The number of degrees of freedom is equal to zero. This can lead to bad initialization.\n";
265 
266  m_residual = m_residualIni = m_residualOld = 0;
267 
268  defaultOptions();
269 
270  m_status = gsStatus::NotStarted;
271 }
272 
273 template <class T>
275 {
276  // Define residual measures:
277  // residual = current residual
278  // residual0 = residual on m_U
279  // residualOld = residual in previous step
280 
281  if (!m_headstart) // no headstart
282  {
283  // We can reset the update to ensure we properly restart
284  if (m_dofs==0) gsWarn<<"The number of degrees of freedom is equal to zero. This can lead to bad initialization.\n";
285  m_DeltaU.setZero(m_dofs);
286  // Compute current residual and its norm
287  m_R = this->_computeResidual(m_U);
288  m_residual = m_R.norm();
289  // If the residual is 0 (e.g. with purely displacment loading), we set it to 1 to allow divisions
290  if (m_residual==0) m_residual=1;
291  // All residual norms are equal
292  m_residualIni = m_residualOld = m_residual;
293  }
294  else
295  {
296  // If we have a headstart, we need to compute Residual0 on the solution m_U
297  // Compute current residual and its norm
298  m_R = this->_computeResidual(m_U + m_DeltaU);
299  m_residual = m_R.norm();
300  // If the residual is 0 (e.g. with purely displacment loading), we set it to 1 to allow divisions
301  if (m_residual==0) m_residual=1;
302  // The previous step residual is the same as the residual
303  m_residualOld = m_residual;
304  // Residual0 is the residual without m_DeltaU
305  m_residualIni = this->_computeResidual(m_U).norm();
306  // If the residual is 0 (e.g. with purely displacment loading), we set it to 1 to allow divisions
307  if (m_residualIni==0) m_residualIni=1;
308 
309  // Now we can reset the headstart
310  m_headstart = false;
311  }
312 
313  // Reset incremental update
314  m_deltaU.setZero(m_dofs);
315 
316 }
317 
318 } // namespace gismo
Step did not converge.
void _factorizeMatrix(const gsSparseMatrix< T > &jacMat) const
Factorizes the jacMat.
Definition: gsStaticNewton.hpp:216
void getOptions() override
See gsStaticBase.
Definition: gsStaticNewton.hpp:29
void _start()
Starts the method.
Definition: gsStaticNewton.hpp:274
gsVector< T > _solveLinear()
Perform a linear solve.
Definition: gsStaticNewton.hpp:102
Assembly problem in step.
Static solver using a newton method.
Definition: gsStaticNewton.h:31
Assembly failed due to an error in the expression (e.g. overflow)
#define index_t
Definition: gsConfig.h:32
gsStatus
Definition: gsStructuralAnalysisTypes.h:20
#define gsWarn
Definition: gsDebug.h:50
gsVector< T > _solveSystem(const gsVector< T > &F)
Solves the system with RHS F and LHS the Jacobian.
Definition: gsStaticNewton.hpp:231
#define gsInfo
Definition: gsDebug.h:43
ALM has not started yet.
void initOutput() override
See gsStaticBase.
Definition: gsStaticNewton.hpp:43
void _init()
Initializes the method.
Definition: gsStaticNewton.hpp:252
void reset() override
See gsStaticBase.
Definition: gsStaticNewton.hpp:244
gsStatus solveLinear()
Perform a linear solve.
Definition: gsStaticNewton.hpp:76
gsVector< T > _solveNonlinear()
Perform a nonlinear solve.
Definition: gsStaticNewton.hpp:143
void stepOutput(index_t k) override
See gsStaticBase.
Definition: gsStaticNewton.hpp:59
void defaultOptions() override
See gsStaticBase.
Definition: gsStaticNewton.hpp:21