MBDyn-1.7.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups
gmres.cc
Go to the documentation of this file.
1 /* $Header: /var/cvs/mbdyn/mbdyn/mbdyn-1.0/mbdyn/base/gmres.cc,v 1.61 2017/01/12 14:46:09 masarati Exp $ */
2 /*
3  * MBDyn (C) is a multibody analysis code.
4  * http://www.mbdyn.org
5  *
6  * Copyright (C) 1996-2017
7  *
8  * Pierangelo Masarati <masarati@aero.polimi.it>
9  * Paolo Mantegazza <mantegazza@aero.polimi.it>
10  *
11  * Dipartimento di Ingegneria Aerospaziale - Politecnico di Milano
12  * via La Masa, 34 - 20156 Milano, Italy
13  * http://www.aero.polimi.it
14  *
15  * Changing this copyright notice is forbidden.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation (version 2 of the License).
20  *
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */
31 
32  /*
33  *
34  * Copyright (C) 2003-2017
35  * Giuseppe Quaranta <quaranta@aero.polimi.it>
36  *
37  * classi che implementano la risoluzione del sistema nonlineare
38  */
39 
40 #include "mbconfig.h" /* This goes first in every *.c,*.cc file */
41 
42 #include <limits>
43 #include <cmath>
44 #include <cstdlib>
45 
46 #include "solver.h"
47 #include "gmres.h"
48 
49 #ifdef USE_MPI
50 #include "mbcomm.h"
51 #include "schsolman.h"
52 #endif /* USE_MPI */
53 
54 #include "dofown.h"
55 #include "output.h"
56 
58  const integer iPStep,
59  doublereal ITol,
60  integer MaxIt,
61  doublereal etaMx,
62  doublereal T,
64 : MatrixFreeSolver(PType, iPStep, ITol, MaxIt, etaMx, T, options),
65 v(NULL),
66 s(MaxLinIt + 1), cs(MaxLinIt + 1), sn(MaxLinIt + 1)
67 {
69 }
70 
72 {
73  for (int i = 0; i < MaxLinIt + 1; i++) {
74  v[i].Detach();
75  }
76 
78 }
79 
80 void
82  doublereal &cs, doublereal &sn) const
83 {
84  if (fabs(dy) < std::numeric_limits<doublereal>::epsilon()) {
85  cs = 1.0;
86  sn = 0.0;
87 
88  } else if (fabs(dy) > fabs(dx)) {
89  doublereal temp = dx / dy;
90  sn = 1.0 / sqrt( 1.0 + temp*temp );
91  cs = temp * sn;
92 
93  } else {
94  doublereal temp = dy / dx;
95  cs = 1.0 / sqrt( 1.0 + temp*temp );
96  sn = temp * cs;
97  }
98 }
99 
100 void
102  const doublereal &cs, const doublereal &sn) const
103 {
104  doublereal temp = cs * dx + sn * dy;
105  dy = -sn * dx + cs * dy;
106  dx = temp;
107 }
108 
109 void
112 {
113  for (int i = sz+1; i > 0; i--) {
114  s.PutCoef(i, s(i) / H(i, i));
115  for (int j = i - 1; j > 0; j--) {
116  s.DecCoef(j, H(j, i) * s(i));
117  }
118  }
119 
120  for (int j = 0; j <= sz; j++) {
121  x.ScalarAddMul(v[j], s(j+1));
122  }
123 }
124 
125 void
127  Solver* pS,
128  const integer iMaxIter,
129  const doublereal& Tol,
130  integer& iIterCnt,
131  doublereal& dErr,
132  const doublereal& SolTol,
133  doublereal& dSolErr)
134 {
135  ASSERT(pNLP != NULL);
136  ASSERT(pS != NULL);
137 
139 
140  iIterCnt = 0;
141  dSolErr = 0.;
142  doublereal dErrDiff = 0.;
143 
144  /* external nonlinear iteration */
145 
146  /* riassembla sempre lo jacobiano se l'integratore e' nuovo */
147  if (pNLP != pPrevNLP) {
148  bBuildMat = true;
149  }
150 
151  pPrevNLP = pNLP;
152 
153  pRes = pSM->pResHdl();
154  Size = pRes->iGetSize();
155 
156  doublereal eta = etaMax;
157  doublereal rateo = 0.;
158  doublereal Fnorm = 1.;
159  doublereal resid;
160  doublereal norm1, norm2;
161  VectorHandler* pr;
162 
163  /*
164  * these will be resized (actually allocated)
165  * only the first time they're used, unless
166  * the size of the problem changes
167  *
168  * FIXME: need to review this code.
169  */
170  w.Resize(Size);
171  vHat.Resize(Size);
172  dx.Resize(Size);
173 
174  H.Resize(Size, MaxLinIt + 1);
175 
176  integer TotalIter = 0;
177 
178 #ifdef DEBUG_ITERATIVE
179  std::cout << " Gmres New Step " << std::endl;
180 #endif /* DEBUG_ITERATIVE */
181 
182  doublereal dOldErr = 0.;
183  doublereal dErrFactor = 1.;
184  while (true) {
185 
186 #ifdef USE_EXTERNAL
187  SendExternal();
188 #endif /* USE_EXTERNAL */
189  pRes->Reset();
190  try {
191  pNLP->Residual(pRes);
192  }
194  if (bHonorJacRequest) {
195  bBuildMat = true;
196  }
197  }
198 
199  if (outputRes()) {
200  pS->PrintResidual(*pRes, iIterCnt);
201  }
202 
203  bool bTest = MakeResTest(pS, pNLP, *pRes, Tol, dErr, dErrDiff);
204  if (iIterCnt > 0) {
205  dErrFactor *= dErr/dOldErr;
206  }
207  dOldErr = dErr;
208 
209 #ifdef DEBUG_ITERATIVE
210  std::cerr << "dErr " << dErr << std::endl;
211 #endif /* DEBUG_ITERATIVE */
212 
213  if (outputIters()) {
214 #ifdef USE_MPI
215  if (!bParallel || MBDynComm.Get_rank() == 0)
216 #endif /* USE_MPI */
217  {
218  silent_cout("\tIteration(" << iIterCnt << ") " << dErr);
219  if (bBuildMat && !bTest) {
220  silent_cout(" J");
221  }
222  silent_cout(std::endl);
223  }
224  }
225 
226  pS->CheckTimeStepLimit(dErr, dErrDiff);
227 
228  if (bTest) {
229  return;
230  }
231  if (!std::isfinite(dErr)) {
233  }
234  if (iIterCnt >= std::abs(iMaxIter)) {
235  if (iMaxIter < 0 && dErrFactor < 1.) {
236  return;
237  }
238  if (outputBailout()) {
239  pS->PrintResidual(*pRes, iIterCnt);
240  }
242  }
243  rateo = dErr*dErr/Fnorm;
244 
245 #ifdef DEBUG_ITERATIVE
246  std::cerr << "rateo " << rateo << std::endl;
247 #endif /* DEBUG_ITERATIVE */
248 
249  Fnorm = dErr*dErr;
250 
251  iIterCnt++;
252 
253  /* inner iteration to solve the linear system */
254 
255  /* Gmres(m) Iterative solver */
256  DEBUGCOUT("Using Gmres(m) iterative solver" << std::endl);
257 
258  /* r0 = b- A*x0 but we choose (x0 = 0) => r0 = b */
259  /* N.B. *pRes = -F(0) */
260 
261  pr = pRes;
262  doublereal LocTol = eta * dErr;
263 
264 #ifdef DEBUG_ITERATIVE
265  std::cerr << "LocTol " << LocTol << std::endl;
266 #endif /* DEBUG_ITERATIVE */
267 
268  resid = dErr;
269  dx.Reset();
270 
271  if (bBuildMat) {
272  pSM->MatrReset();
273 
274 rebuild_matrix:;
275  try {
276  pNLP->Jacobian(pSM->pMatHdl());
277 
279  silent_cout("NewtonRaphsonSolver: "
280  "rebuilding matrix..."
281  << std::endl);
282 
283  /* need to rebuild the matrix... */
284  pSM->MatrInitialize();
285  goto rebuild_matrix;
286 
287  } catch (...) {
288  throw;
289  }
290 
291  bBuildMat = false;
292  TotalIter = 0;
293  TotJac++;
294 
295 #ifdef DEBUG_ITERATIVE
296  std::cerr << "Jacobian " << std::endl;
297 #endif /* DEBUG_ITERATIVE */
298 
299  }
300 
301  int i = 0;
302  v[0].Resize(Size);
303  v[0].ScalarMul(*pr, 1./resid);
304  s.Reset();
305  cs.Reset();
306  sn.Reset();
307  s.PutCoef(1, resid);
308  while ((i < MaxLinIt)) {
309 
310 #ifdef DEBUG_ITERATIVE
311  std::cout << "v[i]:" << i << std::endl;
312  for (int iTmpCnt = 1; iTmpCnt <= Size; iTmpCnt++) {
313  std::cout << "Dof" << std::setw(4) << iTmpCnt << ": "
314  << v[i](iTmpCnt) << std::endl;
315  }
316 #endif /* DEBUG_ITERATIVE */
317 
318  pPM->Precond(v[i], vHat, pSM);
319 
320 #ifdef DEBUG_ITERATIVE
321  std::cout << "vHat:" << std::endl;
322  for (int iTmpCnt = 1; iTmpCnt <= Size; iTmpCnt++) {
323  std::cout << "Dof" << std::setw(4) << iTmpCnt << ": "
324  << vHat(iTmpCnt) << std::endl;
325  }
326 #endif /* DEBUG_ITERATIVE */
327 
328  pNLP->EvalProd(Tau, *pr, vHat, w);
329 
330 #if 0
331  (pSM->pMatHdl())->MatVecMul(w, vHat);
332 #endif
333 
334 #ifdef DEBUG_ITERATIVE
335  std::cout << "w:" << std::endl;
336  for (int iTmpCnt = 1; iTmpCnt <= Size; iTmpCnt++) {
337  std::cout << "Dof" << std::setw(4) << iTmpCnt << ": "
338  << w(iTmpCnt) << std::endl;
339  }
340 #endif /* DEBUG_ITERATIVE */
341 
342  norm1 = w.Norm();
343 
344 #ifdef DEBUG_ITERATIVE
345  std::cerr << "norm1: " << norm1 << std::endl;
346 #endif /* DEBUG_ITERATIVE */
347 
348  for (int k = 0; k <= i; k++) {
349  H(k+1, i+1) = w.InnerProd(v[k]);
350 
351 #ifdef DEBUG_ITERATIVE
352  std::cerr << "H(k, i): " << k+1 << " " << i+1 << " "<< H(k+1, i+1) << std::endl;
353 #endif /* DEBUG_ITERATIVE */
354 
355  w.ScalarAddMul(v[k], -H(k+1, i+1));
356  }
357  H(i+2, i+1) = w.Norm();
358 
359 #ifdef DEBUG_ITERATIVE
360  std::cerr << "w.Norm(): " << w.Norm() << std::endl;
361  std::cerr << "H(i+1, i): " << i+2 << " " << i+1 << " " << H(i+2, i+1) << std::endl;
362 #endif /* DEBUG_ITERATIVE */
363 
364  norm2 = H(i+2, i+1);
365 
366 #ifdef DEBUG_ITERATIVE
367  std::cerr << "norm2: " << norm2 << std::endl;
368 #endif /* DEBUG_ITERATIVE */
369 
370  v[i+1].Resize(Size);
371 
372  /* Reorthogonalize? */
373  if (.001*norm2/norm1 < std::numeric_limits<doublereal>::epsilon()) {
374  for (int k = 0; k <= i; k++) {
375  doublereal hr = v[k].InnerProd(w);
376  H(k+1, i+1) += hr;
377  w.ScalarAddMul(v[k], -hr);
378 
379 #ifdef DEBUG_ITERATIVE
380  std::cerr << "Reorthogonalize: " << std::endl;
381 #endif /* DEBUG_ITERATIVE */
382 
383  }
384  H(i+2, i+1) = w.Norm();
385  }
386  if (fabs(H(i+2, i+1)) > std::numeric_limits<doublereal>::epsilon()) {
387  v[i+1].ScalarMul(w, 1./H(i+2, i+1));
388 
389 #ifdef DEBUG_ITERATIVE
390  std::cout << "v[i+1]:" << i+1 << std::endl;
391 
392  for (int iTmpCnt = 1; iTmpCnt <= Size; iTmpCnt++) {
393  std::cout << "Dof" << std::setw(4) << iTmpCnt << ": "
394  << v[i+1](iTmpCnt) << std::endl;
395  }
396 #endif /* DEBUG_ITERATIVE */
397  } else {
398  /* happy breakdown !! */
399 
400 #ifdef DEBUG_ITERATIVE
401  std::cerr << "happy breakdown: " << std::endl;
402 #endif /* DEBUG_ITERATIVE */
403 
404  v[i+1].Reset();
405  }
406  for (int k = 0; k < i; k++) {
407  ApplyPlaneRotation(H(k+1, i+1), H(k+2, i+1),
408  cs(k+1),
409  sn(k+1));
410 
411 #ifdef DEBUG_ITERATIVE
412  std::cerr << "H(k, i): " << k+1 << " " << i+1 << " " << H(k+1, i+1) << std::endl;
413  std::cerr << "H(k+1, i): " << k+2 << " " << i+1 << " " << H(k+2, i+1) << std::endl;
414 #endif /* DEBUG_ITERATIVE */
415 
416  }
417 
418  GeneratePlaneRotation(H(i+1, i+1), H(i+2, i+1),
419  cs(i+1), sn(i+1));
420 
421 #ifdef DEBUG_ITERATIVE
422  std::cerr << "cs(i): " << cs(i+1) << std::endl;
423  std::cerr << "sn(i): " << sn(i+1) << std::endl;
424 #endif /* DEBUG_ITERATIVE */
425 
426  ApplyPlaneRotation(H(i+1, i+1), H(i+2, i+1),
427  cs(i+1), sn(i+1));
428  ApplyPlaneRotation(s(i+1), s(i+2), cs(i+1), sn(i+1));
429  if ((resid = fabs(s(i+2))) < LocTol) {
430 
431 #ifdef DEBUG_ITERATIVE
432  std::cerr << "resid 1: " << resid << std::endl;
433 #endif /* DEBUG_ITERATIVE */
434 
435  Backsolve(dx, i, s, v);
436  pPM->Precond(dx, dx, pSM);
437 
438 #ifdef DEBUG_ITERATIVE
439  std::cout << "dx:" << std::endl;
440  for (int iTmpCnt = 1; iTmpCnt <= Size; iTmpCnt++) {
441  std::cout << "Dof" << std::setw(4) << iTmpCnt << ": "
442  << dx(iTmpCnt) << std::endl;
443  }
444 #endif /* DEBUG_ITERATIVE */
445 
446  break;
447  }
448 
449 #ifdef DEBUG_ITERATIVE
450  std::cerr << "resid 2 : " << resid << std::endl;
451 #endif /* DEBUG_ITERATIVE */
452 
453  TotalIter++;
454  i++;
455  }
456  if (i == MaxLinIt) {
457  Backsolve(dx, MaxLinIt-1, s, v);
458  pPM->Precond(dx, dx, pSM);
459  silent_cerr("Iterative inner solver didn't converge."
460  << " Continuing..." << std::endl);
461  }
462 
463  /* se ha impiegato troppi passi riassembla lo jacobiano */
464 
465  if (TotalIter >= PrecondIter) {
466  bBuildMat = true;
467  }
468  /* calcola il nuovo eta */
469  doublereal etaNew = gamma * rateo;
470  doublereal etaBis;
471  if ((etaBis = gamma*eta*eta) > .1) {
472  etaNew = (etaNew > etaBis) ? etaNew : etaBis;
473  }
474  eta = (etaNew < etaMax) ? etaNew : etaMax;
475  /* prevent oversolving */
476  etaBis = .5*Tol/dErr;
477  eta = (eta > etaBis) ? eta : etaBis;
478 
479 #ifdef DEBUG_ITERATIVE
480  std::cerr << "eta " << eta << std::endl;
481 #endif /* DEBUG_ITERATIVE */
482 
483  if (outputSol()) {
484  pS->PrintSolution(dx, iIterCnt);
485  }
486 
487  pNLP->Update(&dx);
488 
489  bTest = MakeSolTest(pS, dx, SolTol, dSolErr);
490  if (outputIters()) {
491 #ifdef USE_MPI
492  if (!bParallel || MBDynComm.Get_rank() == 0)
493 #endif /* USE_MPI */
494  {
495  silent_cout("\t\tSolErr "
496  << dSolErr << std::endl);
497  }
498  }
499 
500  if (bTest) {
502  }
503 
504  // allow to bail out in case of multiple CTRL^C
507  }
508  }
509 }
510 
void GeneratePlaneRotation(const doublereal &dx, const doublereal &dy, doublereal &cs, doublereal &sn) const
Definition: gmres.cc:81
Preconditioner * pPM
Definition: mfree.h:61
FullMatrixHandler H
Definition: gmres.h:51
virtual void Reset(void)=0
virtual VectorHandler * pResHdl(void) const =0
virtual SolutionManager * pGetSolutionManager(void) const
Definition: solver.h:398
MyVectorHandler sn
Definition: gmres.h:50
virtual void Jacobian(MatrixHandler *pJac) const =0
bool outputIters(void) const
integer TotJac
Definition: nonlin.h:252
#define MBDYN_EXCEPT_ARGS
Definition: except.h:63
bool outputBailout(void) const
void ApplyPlaneRotation(doublereal &dx, doublereal &dy, const doublereal &cs, const doublereal &sn) const
Definition: gmres.cc:101
virtual bool MakeSolTest(Solver *pS, const VectorHandler &Vec, const doublereal &dTol, doublereal &dTest)
Definition: nonlin.cc:497
virtual void PrintResidual(const VectorHandler &Res, integer iIterCnt) const
Definition: solver.cc:5194
virtual bool MakeResTest(Solver *pS, const NonlinearProblem *pNLP, const VectorHandler &Vec, const doublereal &dTol, doublereal &dTest, doublereal &dTestDiff)
Definition: nonlin.cc:474
bool bBuildMat
Definition: mfree.h:69
virtual void CheckTimeStepLimit(doublereal dErr, doublereal dErrDiff) const
Definition: solver.cc:5205
#define SAFEDELETEARR(pnt)
Definition: mynewmem.h:713
MyVectorHandler * v
Definition: gmres.h:49
virtual doublereal InnerProd(const VectorHandler &VH) const
Definition: vh.cc:269
void Detach(void)
Definition: vh.cc:403
virtual VectorHandler & ScalarAddMul(const VectorHandler &VH, const VectorHandler &VH1, const doublereal &d)
Definition: vh.cc:499
bool outputRes(void) const
integer Size
Definition: nonlin.h:251
virtual void Residual(VectorHandler *pRes) const =0
virtual void Resize(integer iNewRows, integer iNewCols)
Definition: fullmh.cc:174
virtual integer iGetSize(void) const =0
virtual doublereal Norm(void) const
Definition: vh.cc:262
GradientExpression< UnaryExpr< FuncFabs, Expr > > fabs(const GradientExpression< Expr > &u)
Definition: gradient.h:2973
virtual void PutCoef(integer iRow, const doublereal &dCoef)
Definition: vh.h:261
virtual VectorHandler & ScalarMul(const VectorHandler &VH, const doublereal &d)
Definition: vh.cc:519
virtual void Resize(integer iSize)
Definition: vh.cc:347
int mbdyn_stop_at_end_of_iteration(void)
Definition: solver.cc:172
integer PrecondIter
Definition: mfree.h:68
virtual void DecCoef(integer iRow, const doublereal &dCoef)=0
virtual void Solve(const NonlinearProblem *NLP, Solver *pS, const integer iMaxIter, const doublereal &Tol, integer &iIterCnt, doublereal &dErr, const doublereal &SolTol, doublereal &dSolErr)
Definition: gmres.cc:126
bool outputSol(void) const
~Gmres(void)
Definition: gmres.cc:71
const NonlinearProblem * pPrevNLP
Definition: mfree.h:70
virtual void EvalProd(doublereal Tau, const VectorHandler &f0, const VectorHandler &w, VectorHandler &z) const =0
virtual MatrixHandler * pMatHdl(void) const =0
#define DEBUGCOUT(msg)
Definition: myassert.h:232
virtual void MatrReset(void)=0
Gmres(const Preconditioner::PrecondType PType, const integer iPStep, doublereal ITol, integer MaxIt, doublereal etaMx, doublereal T, const NonlinearSolverOptions &options)
Definition: gmres.cc:57
#define ASSERT(expression)
Definition: colamd.c:977
virtual void Precond(VectorHandler &b, VectorHandler &x, SolutionManager *pSM) const =0
GradientExpression< UnaryExpr< FuncSqrt, Expr > > sqrt(const GradientExpression< Expr > &u)
Definition: gradient.h:2974
virtual void MatrInitialize(void)
Definition: solman.cc:72
virtual void PutCoef(integer iRow, const doublereal &dCoef)=0
virtual void Reset(void)
Definition: vh.cc:459
struct option options[]
Definition: ann_in.c:46
Definition: solver.h:78
MyVectorHandler dx
Definition: gmres.h:50
integer MaxLinIt
Definition: mfree.h:64
doublereal Tau
Definition: mfree.h:65
virtual VectorHandler & ScalarAddMul(const VectorHandler &VH, const doublereal &d)
Definition: vh.cc:108
MyVectorHandler cs
Definition: gmres.h:50
#define SAFENEWARRNOFILL(pnt, item, sz)
Definition: mynewmem.h:704
MyVectorHandler vHat
Definition: gmres.h:50
VectorHandler * pRes
Definition: mfree.h:62
virtual void PrintSolution(const VectorHandler &Sol, integer iIterCnt) const
Definition: solver.cc:5200
doublereal etaMax
Definition: mfree.h:67
MyVectorHandler s
Definition: gmres.h:50
virtual void Update(const VectorHandler *pSol) const =0
double doublereal
Definition: colamd.c:52
long int integer
Definition: colamd.c:51
doublereal gamma
Definition: mfree.h:66
void Backsolve(VectorHandler &x, integer sz, VectorHandler &s, MyVectorHandler *v)
Definition: gmres.cc:110
MyVectorHandler w
Definition: gmres.h:50