OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
nrsolver.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include "nrsolver.h"
36 #include "verbose.h"
37 #include "timestep.h"
38 #include "mathfem.h"
39 // includes for ddc - not very clean (NumMethod knows what is "node" and "dof")
40 #include "node.h"
41 #include "element.h"
43 #include "dof.h"
44 #include "function.h"
45 #include "linesearch.h"
46 #include "classfactory.h"
47 #include "exportmodulemanager.h"
48 #include "engngm.h"
49 #include "parallelcontext.h"
50 #include "unknownnumberingscheme.h"
51 
52 #ifdef __PETSC_MODULE
53  #include "petscsolver.h"
54  #include "petscsparsemtrx.h"
55 #endif
56 
57 #include <cstdio>
58 
59 namespace oofem {
60 #define nrsolver_ERROR_NORM_SMALL_NUM 1.e-6
61 #define NRSOLVER_MAX_REL_ERROR_BOUND 1.e20
62 #define NRSOLVER_MAX_RESTARTS 4
63 #define NRSOLVER_RESET_STEP_REDUCE 0.25
64 #define NRSOLVER_DEFAULT_NRM_TICKS 10
65 
67 
69  SparseNonLinearSystemNM(d, m), prescribedDofs(), prescribedDofsValues()
70 {
71  //
72  // constructor
73  //
74  nsmax = 60; // default maximum number of sweeps allowed
75  deltaL = 1.0;
76  NR_Mode = NR_OldMode = nrsolverModifiedNRM;
77  NR_ModeTick = -1; // do not switch to calm_NR_OldMode
78  MANRMSteps = 0;
79  numberOfPrescribedDofs = 0;
80  prescribedDofsFlag = false;
81  prescribedEqsInitFlag = false;
82  prescribedDisplacementTF = 0;
83  lsFlag = 0; // no line-search
84 
85  constrainedNRFlag = false;
86  this->forceErrVecOld.resize(0);
87  this->forceErrVec.resize(0);
88  constrainedNRalpha = 0.5; // default
89 
90  smConstraintVersion = 0;
91  mCalcStiffBeforeRes = true;
92 
93  maxIncAllowed = 1.0e20;
94 }
95 
96 
98 {
99 }
100 
101 
104 {
105  IRResultType result; // Required by IR_GIVE_FIELD macro
106 
107  // Choosing a big "enough" number. (Alternative: Force input of maxinter)
108  nsmax = ( int ) 1e8;
110  if ( nsmax < 0 ) {
111  OOFEM_ERROR("nsmax < 0");
112  }
113 
114  minIterations = 0;
116 
117  minStepLength = 0.0;
119 
120  // read if MANRM method is used
121  MANRMSteps = 0;
123  if ( MANRMSteps > 0 ) {
125  } else {
127  }
128 
129  int _val = 0;
131  solverType = ( LinSystSolverType ) _val;
132  this->giveLinearSolver()->initializeFrom(ir); // make sure that linear solver is initialized from ir as well
133 
134  // read relative error tolerances of the solver
135  // if rtolv provided set to this tolerance both rtolf and rtold
136  rtolf.resize(1);
137  rtolf.at(1) = 1.e-3; // Default value.
138  rtold.resize(1);
139  rtold = FloatArray{0.0}; // Default off (0.0 or negative values mean that residual is ignored)
142 
143  // read optional force and displacement tolerances
146 
153 
156  OOFEM_ERROR("direct displacement mask size mismatch");
157  }
158 
159  if ( numberOfPrescribedDofs ) {
160  prescribedDofsFlag = true;
161  } else {
162  prescribedDofsFlag = false;
163  }
164 
165  this->lsFlag = 0;
167 
168  if ( this->lsFlag ) {
170  }
171 
172  int calcStiffBeforeResFlag = 1;
173  IR_GIVE_OPTIONAL_FIELD(ir, calcStiffBeforeResFlag, _IFT_NRSolver_calcstiffbeforeres);
174  if ( calcStiffBeforeResFlag == 0 ) {
175  mCalcStiffBeforeRes = false;
176  }
177 
178 
179  this->constrainedNRminiter = 0;
181  this->constrainedNRFlag = this->constrainedNRminiter != 0;
182 
183 
185 
186  dg_forceScale.clear();
187  if ( ir->hasField(_IFT_NRSolver_forceScale) ) {
188  IntArray dofs;
189  FloatArray forces;
192  for ( int i = 0; i < dofs.giveSize(); ++i ) {
193  dg_forceScale[dofs[i]] = forces[i];
194  }
195  }
196 
198 }
199 
200 
201 NM_Status
203  FloatArray &X, FloatArray &dX, FloatArray &F,
204  const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm,
205  int &nite, TimeStep *tStep)
206 //
207 // this function solve the problem of the unbalanced equilibrium
208 // using NR scheme
209 //
210 //
211 {
212  // residual, iteration increment of solution, total external force
213  FloatArray rhs, ddX, RT;
214  double RRT;
215  int neq = X.giveSize();
216  bool converged, errorOutOfRangeFlag;
217  ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
218 
219  if ( engngModel->giveProblemScale() == macroScale ) {
220  OOFEM_LOG_INFO("NRSolver: Iteration");
221  if ( rtolf.at(1) > 0.0 ) {
222  OOFEM_LOG_INFO(" ForceError");
223  }
224  if ( rtold.at(1) > 0.0 ) {
225  OOFEM_LOG_INFO(" DisplError");
226  }
227  OOFEM_LOG_INFO("\n----------------------------------------------------------------------------\n");
228  }
229 
230  l = 1.0;
231 
232  NM_Status status = NM_None;
233  this->giveLinearSolver();
234 
235  // compute total load R = R+R0
236  RT = R;
237  if ( R0 ) {
238  RT.add(* R0);
239  }
240 
241  RRT = parallel_context->localNorm(RT);
242  RRT *= RRT;
243 
244  ddX.resize(neq);
245  ddX.zero();
246 
247  // Fetch the matrix before evaluating internal forces.
248  // This is intentional, since its a simple way to drastically increase convergence for nonlinear problems.
249  // (This old tangent is just used)
250  // This improves convergence for many nonlinear problems, but not all. It may actually
251  // cause divergence for some nonlinear problems. Therefore a flag is used to determine if
252  // the stiffness should be evaluated before the residual (default yes). /ES
253 
255  if ( this->prescribedDofsFlag ) {
256  if ( !prescribedEqsInitFlag ) {
257  this->initPrescribedEqs();
258  }
260  }
261 
262  nite = 0;
263  for ( nite = 0; ; ++nite ) {
264  // Compute the residual
266  rhs.beDifferenceOf(RT, F);
267 
268  if ( this->prescribedDofsFlag ) {
269  this->applyConstraintsToLoadIncrement(nite, k, rhs, rlm, tStep);
270  }
271 
272  // convergence check
273  converged = this->checkConvergence(RT, F, rhs, ddX, X, RRT, internalForcesEBENorm, nite, errorOutOfRangeFlag);
274 
275  if ( errorOutOfRangeFlag ) {
276  status = NM_NoSuccess;
277  OOFEM_WARNING("Divergence reached after %d iterations", nite);
278  break;
279  } else if ( converged && ( nite >= minIterations ) ) {
280  status |= NM_Success;
281  break;
282  } else if ( nite >= nsmax ) {
283  OOFEM_LOG_DEBUG("Maximum number of iterations reached\n");
284  break;
285  }
286 
287  if ( nite > 0 || !mCalcStiffBeforeRes ) {
288  if ( ( NR_Mode == nrsolverFullNRM ) || ( ( NR_Mode == nrsolverAccelNRM ) && ( nite % MANRMSteps == 0 ) ) ) {
291  }
292  }
293 
294  if ( ( nite == 0 ) && ( deltaL < 1.0 ) ) { // deltaL < 1 means no increment applied, only equilibrate current state
295  rhs.zero();
296  R.zero();
297  ddX = rhs;
298  } else {
299 
300 // if ( engngModel->giveProblemScale() == macroScale ) {
301 // k.writeToFile("k.txt");
302 // }
303 
304  linSolver->solve(k, rhs, ddX);
305  }
306 
307  //
308  // update solution
309  //
310  if ( this->lsFlag && ( nite > 0 ) ) { // Why not nite == 0 ?
311  // line search
312  LineSearchNM :: LS_status LSstatus;
313  double eta;
314  this->giveLineSearchSolver()->solve(X, ddX, F, R, R0, prescribedEqs, 1.0, eta, LSstatus, tStep);
315  } else if ( this->constrainedNRFlag && ( nite > this->constrainedNRminiter ) ) {
318  OOFEM_LOG_INFO("Constraining increment to be %e times full increment...\n", this->constrainedNRalpha);
319  ddX.times(this->constrainedNRalpha);
320  }
321  //this->giveConstrainedNRSolver()->solve(X, & ddX, this->forceErrVec, this->forceErrVecOld, status, tStep);
322  }
323 
324 
326 
327  double maxInc = 0.0;
328  for ( double inc : ddX ) {
329  if(fabs(inc) > maxInc) {
330  maxInc = fabs(inc);
331  }
332  }
333 
334  if(maxInc > maxIncAllowed) {
335  if ( engngModel->giveProblemScale() == macroScale ) {
336  printf("Restricting increment. maxInc: %e\n", maxInc);
337  }
338  ddX.times(maxIncAllowed/maxInc);
339  }
340 
342 
343 
344  X.add(ddX);
345  dX.add(ddX);
346  tStep->incrementStateCounter(); // update solution state counter
347  tStep->incrementSubStepNumber();
348 
350  }
351 
352  // Modify Load vector to include "quasi reaction"
353  if ( R0 ) {
354  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
355  R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R0->at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) );
356  }
357  } else {
358  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
359  R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) );
360  }
361  }
362 
364 
365 #ifdef VERBOSE
366  if ( numberOfPrescribedDofs ) {
367  // print quasi reactions if direct displacement control used
368  OOFEM_LOG_INFO("\n");
369  OOFEM_LOG_INFO("NRSolver: Quasi reaction table \n");
370  OOFEM_LOG_INFO("NRSolver: Node Dof Displacement Force\n");
371  double reaction;
372  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
373  reaction = R.at( prescribedEqs.at(i) );
374  if ( R0 ) {
375  reaction += R0->at( prescribedEqs.at(i) );
376  }
377  lastReactions.at(i) = reaction;
378  OOFEM_LOG_INFO("NRSolver: %-15d %-15d %-+15.5e %-+15.5e\n", prescribedDofs.at(2 * i - 1), prescribedDofs.at(2 * i),
379  X.at( prescribedEqs.at(i) ), reaction);
380  }
381  OOFEM_LOG_INFO("\n");
382  }
383 #endif
384 
385  return status;
386 }
387 
388 
391 {
392  if ( linSolver ) {
393  if ( linSolver->giveLinSystSolverType() == solverType ) {
394  return linSolver.get();
395  } else {
396  linSolver.reset(NULL);
397  }
398  }
399 
401  if ( !linSolver ) {
402  OOFEM_ERROR("linear solver creation failed for lstype %d", solverType);
403  }
404 
405  return linSolver.get();
406 }
407 
408 
409 LineSearchNM *
411 {
412  if ( !linesearchSolver ) {
414  }
415 
416  return linesearchSolver.get();
417 }
418 
419 void
421 {
423  ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
424  int count = 0, ndofman = domain->giveNumberOfDofManagers();
425  IntArray localPrescribedEqs(numberOfPrescribedDofs);
426 
427  for ( int j = 1; j <= ndofman; j++ ) {
428  if ( !parallel_context->isLocal( domain->giveNode(j) ) ) {
429  continue;
430  }
431  int jglobnum = domain->giveNode(j)->giveGlobalNumber();
432  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
433  int inode = prescribedDofs.at(2 * i - 1);
434  int idofid = prescribedDofs.at(2 * i);
435  if ( inode == jglobnum ) {
436  localPrescribedEqs.at(++count) = domain->giveNode(j)->giveDofWithID(idofid)->giveEquationNumber(dn);
437  continue;
438  }
439  }
440  }
441 
442  prescribedEqs.resize(count);
443  for ( int i = 1; i <= count; i++ ) {
444  prescribedEqs.at(i) = localPrescribedEqs.at(i);
445  }
446 
447  numberOfPrescribedDofs = count;
448 
449  this->prescribedEqsInitFlag = true;
450 }
451 
452 
453 void
455 {
456  if ( this->smConstraintVersion == k.giveVersion() ) {
457  return;
458  }
459 
460 #ifdef __PETSC_MODULE
461  PetscSparseMtrx *lhs = dynamic_cast< PetscSparseMtrx * >(&k);
462  if ( lhs ) {
463  Vec diag;
464  PetscScalar *ptr;
465  int eq;
466 
467  lhs->createVecGlobal(& diag);
468  MatGetDiagonal(* lhs->giveMtrx(), diag);
469  VecGetArray(diag, & ptr);
470  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
471  eq = prescribedEqs.at(i) - 1;
472  MatSetValue(* ( lhs->giveMtrx() ), eq, eq, ptr [ eq ] * 1.e6, INSERT_VALUES);
473  }
474 
475  MatAssemblyBegin(* lhs->giveMtrx(), MAT_FINAL_ASSEMBLY);
476  MatAssemblyEnd(* lhs->giveMtrx(), MAT_FINAL_ASSEMBLY);
477  VecRestoreArray(diag, & ptr);
478  VecDestroy(& diag);
479  if ( numberOfPrescribedDofs ) {
480  this->smConstraintVersion = k.giveVersion();
481  }
482 
483  return;
484  }
485 
486 #endif // __PETSC_MODULE
487  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
488  k.at( prescribedEqs.at(i), prescribedEqs.at(i) ) *= 1.e6;
489  }
490 
491  if ( numberOfPrescribedDofs ) {
492  this->smConstraintVersion = k.giveVersion();
493  }
494 }
495 
496 
497 void
500 {
502  if ( ( rlm == rlm_total ) && ( !tStep->isTheFirstStep() ) ) {
503  //factor -= engngModel->giveDomain(1)->giveFunction(prescribedDisplacementTF)->
504  // at(tStep->givePreviousStep()->giveTime()) ;
506  evaluateAtTime( tStep->giveTargetTime() - tStep->giveTimeIncrement() );
507  }
508 
509  if ( nite == 0 ) {
510 #if 0
511  #ifdef __PETSC_MODULE
512  if ( solverType == ST_Petsc ) {
513  //Natural2LocalOrdering* n2lpm = engngModel->giveParallelContext(1)->giveN2Lmap();
514  //IntArray* map = n2lpm->giveN2Lmap();
515  for ( i = 1; i <= prescribedEqs.giveSize(); i++ ) {
516  eq = prescribedEqs.at(i);
517  R.at(eq) = prescribedDofsValues.at(i) * factor; // local eq
518  }
519 
520  return;
521  }
522 
523  #endif
524 #else
525  #ifdef __PETSC_MODULE
526  const PetscSparseMtrx *lhs = dynamic_cast< const PetscSparseMtrx * >(&k);
527  if ( lhs ) {
528  Vec diag;
529  PetscScalar *ptr;
530  lhs->createVecGlobal(& diag);
531  MatGetDiagonal(* ( const_cast< PetscSparseMtrx * >(lhs)->giveMtrx() ), diag);
532  VecGetArray(diag, & ptr);
533 
534  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
535  int eq = prescribedEqs.at(i) - 1;
536  R.at(eq + 1) = ptr [ eq ] * prescribedDofsValues.at(i) * factor;
537  }
538 
539  VecRestoreArray(diag, & ptr);
540  VecDestroy(& diag);
541  return;
542  }
543  #endif
544 #endif
545  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
546  int eq = prescribedEqs.at(i);
547  R.at(eq) = k.at(eq, eq) * prescribedDofsValues.at(i) * factor;
548  }
549  } else {
550  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
551  R.at( prescribedEqs.at(i) ) = 0.0;
552  }
553  }
554 }
555 
556 
557 void
558 NRSolver :: printState(FILE *outputStream)
559 {
560 #ifdef VERBOSE
561  // print quasi reactions if direct displacement control used
562  fprintf(outputStream, "\nQuasi reaction table:\n\n");
563  fprintf(outputStream, " node dof force\n");
564  fprintf(outputStream, "============================\n");
565  if ( lastReactions.giveSize() == 0 ) {
566  return;
567  }
568 
569  double reaction;
570  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
571  reaction = lastReactions.at(i);
572  fprintf(outputStream, "%6d %3d %+11.5e\n", prescribedDofs.at(2 * i - 1), prescribedDofs.at(2 * i), reaction);
573  }
574  fprintf(outputStream, "============================\n\n");
575 #endif
576 }
577 
578 
579 bool
581  double RRT, const FloatArray &internalForcesEBENorm,
582  int nite, bool &errorOutOfRange)
583 {
584  double forceErr, dispErr;
585  FloatArray dg_forceErr, dg_dispErr, dg_totalLoadLevel, dg_totalDisp;
586  bool answer;
588  ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
589 
590  /*
591  * The force errors are (if possible) evaluated as relative errors.
592  * If the norm of applied load vector is zero (one may load by temperature, etc)
593  * then the norm of reaction forces is used in relative norm evaluation.
594  *
595  * Note: This is done only when all dofs are included (nccdg = 0). Not implemented if
596  * multiple convergence criteria are used.
597  *
598  */
599 
600  answer = true;
601  errorOutOfRange = false;
602 
603  // Store the errors associated with the dof groups
604  if ( this->constrainedNRFlag ) {
605  this->forceErrVecOld = this->forceErrVec; // copy the old values
606  this->forceErrVec.resize( internalForcesEBENorm.giveSize() );
607  forceErrVec.zero();
608  }
609 
610  if ( internalForcesEBENorm.giveSize() > 1 ) { // Special treatment when just one norm is given; No grouping
611  int nccdg = this->domain->giveMaxDofID();
612  // Keeps tracks of which dof IDs are actually in use;
613  IntArray idsInUse(nccdg);
614  idsInUse.zero();
615  // zero error norms per group
616  dg_forceErr.resize(nccdg);
617  dg_forceErr.zero();
618  dg_dispErr.resize(nccdg);
619  dg_dispErr.zero();
620  dg_totalLoadLevel.resize(nccdg);
621  dg_totalLoadLevel.zero();
622  dg_totalDisp.resize(nccdg);
623  dg_totalDisp.zero();
624  // loop over dof managers
625  for ( auto &dofman : domain->giveDofManagers() ) {
626  if ( !parallel_context->isLocal(dofman.get()) ) {
627  continue;
628  }
629 
630  // loop over individual dofs
631  for ( Dof *dof: *dofman ) {
632  if ( !dof->isPrimaryDof() ) {
633  continue;
634  }
635  int eq = dof->giveEquationNumber(dn);
636  int dofid = dof->giveDofID();
637  if ( !eq ) {
638  continue;
639  }
640 
641  dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
642  dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
643  dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
644  dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
645  idsInUse.at(dofid)++;
646  } // end loop over DOFs
647  } // end loop over dof managers
648 
649  // loop over elements and their DOFs
650  for ( auto &elem : domain->giveElements() ) {
651  if ( elem->giveParallelMode() != Element_local ) {
652  continue;
653  }
654 
655  // loop over element internal Dofs
656  for ( int idofman = 1; idofman <= elem->giveNumberOfInternalDofManagers(); idofman++ ) {
657  DofManager *dofman = elem->giveInternalDofManager(idofman);
658  // loop over individual dofs
659  for ( Dof *dof: *dofman ) {
660  if ( !dof->isPrimaryDof() ) {
661  continue;
662  }
663  int eq = dof->giveEquationNumber(dn);
664  int dofid = dof->giveDofID();
665 
666  if ( !eq ) {
667  continue;
668  }
669 
670  dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
671  dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
672  dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
673  dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
674  idsInUse.at(dofid)++;
675  } // end loop over DOFs
676  } // end loop over element internal dofmans
677  } // end loop over elements
678 
679  // loop over boundary conditions and their internal DOFs
680  for ( auto &bc : domain->giveBcs() ) {
681  // loop over element internal Dofs
682  for ( int idofman = 1; idofman <= bc->giveNumberOfInternalDofManagers(); idofman++ ) {
683  DofManager *dofman = bc->giveInternalDofManager(idofman);
684  // loop over individual dofs
685  for ( Dof *dof: *dofman ) {
686  if ( !dof->isPrimaryDof() ) {
687  continue;
688  }
689  int eq = dof->giveEquationNumber(dn);
690  int dofid = dof->giveDofID();
691 
692  if ( !eq ) {
693  continue;
694  }
695 
696  dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
697  dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
698  dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
699  dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
700  idsInUse.at(dofid)++;
701  } // end loop over DOFs
702  } // end loop over element internal dofmans
703  } // end loop over elements
704 
705  // exchange individual partition contributions (simultaneously for all groups)
706  FloatArray collectiveErr(nccdg);
707  parallel_context->accumulate(dg_forceErr, collectiveErr);
708  dg_forceErr = collectiveErr;
709  parallel_context->accumulate(dg_dispErr, collectiveErr);
710  dg_dispErr = collectiveErr;
711  parallel_context->accumulate(dg_totalLoadLevel, collectiveErr);
712  dg_totalLoadLevel = collectiveErr;
713  parallel_context->accumulate(dg_totalDisp, collectiveErr);
714  dg_totalDisp = collectiveErr;
715 
716  if ( engngModel->giveProblemScale() == macroScale ) {
717  OOFEM_LOG_INFO("NRSolver: %-5d", nite);
718  }
719 
720  int maxNumPrintouts = 6;
721  int numPrintouts = 0;
722 
723  //bool zeroNorm = false;
724  // loop over dof groups and check convergence individually
725  for ( int dg = 1; dg <= nccdg; dg++ ) {
726 
727  bool zeroFNorm = false, zeroDNorm = false;
728  // Skips the ones which aren't used in this problem (the residual will be zero for these anyway, but it is annoying to print them all)
729  if ( !idsInUse.at(dg) ) {
730  continue;
731  }
732 
733  numPrintouts++;
734 
735  if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts) {
736  OOFEM_LOG_INFO( " %s:", __DofIDItemToString( ( DofIDItem ) dg ).c_str() );
737  }
738 
739  if ( rtolf.at(1) > 0.0 ) {
740  // compute a relative error norm
741  if ( dg_forceScale.find(dg) != dg_forceScale.end() ) {
742  forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) +
743  idsInUse.at(dg)*dg_forceScale[dg]*dg_forceScale[dg] ) );
744  } else if ( ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) >= nrsolver_ERROR_NORM_SMALL_NUM ) {
745  forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) );
746  } else {
747  // If both external forces and internal ebe norms are zero, then the residual must be zero.
748  //zeroNorm = true; // Warning about this afterwards.
749  zeroFNorm = true;
750  forceErr = sqrt( dg_forceErr.at(dg) );
751  }
752 
753  if ( forceErr > rtolf.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
754  errorOutOfRange = true;
755  }
756  if ( forceErr > rtolf.at(1) ) {
757  answer = false;
758  }
759 
760  if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts) {
761  OOFEM_LOG_INFO(zeroFNorm ? " *%.3e" : " %.3e", forceErr);
762  }
763 
764  // Store the errors from the current iteration
765  if ( this->constrainedNRFlag ) {
766  forceErrVec.at(dg) = forceErr;
767  }
768  }
769 
770  if ( rtold.at(1) > 0.0 ) {
771  // compute displacement error
772  if ( dg_totalDisp.at(dg) > nrsolver_ERROR_NORM_SMALL_NUM ) {
773  dispErr = sqrt( dg_dispErr.at(dg) / dg_totalDisp.at(dg) );
774  } else {
776  //zeroNorm = true; // Warning about this afterwards.
777  //zeroDNorm = true;
778  dispErr = sqrt( dg_dispErr.at(dg) );
779  }
780  if ( dispErr > rtold.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
781  errorOutOfRange = true;
782  }
783  if ( dispErr > rtold.at(1) ) {
784  answer = false;
785  }
786 
787  if ( engngModel->giveProblemScale() == macroScale && numPrintouts <= maxNumPrintouts) {
788  OOFEM_LOG_INFO(zeroDNorm ? " *%.3e" : " %.3e", dispErr);
789  }
790  }
791  }
792 
793 
794  if ( engngModel->giveProblemScale() == macroScale ) {
795  OOFEM_LOG_INFO("\n");
796  }
797 
798  //if ( zeroNorm ) OOFEM_WARNING("Had to resort to absolute error measure (marked by *)");
799  } else { // No dof grouping
800  double dXX, dXdX;
801 
802  if ( engngModel->giveProblemScale() == macroScale ) {
803  OOFEM_LOG_INFO("NRSolver: %-15d", nite);
804  } else {
805 // OOFEM_LOG_INFO(" NRSolver: %-15d", nite);
806  }
807 
808 
809  forceErr = parallel_context->localNorm(rhs);
810  forceErr *= forceErr;
811  dXX = parallel_context->localNorm(X);
812  dXX *= dXX; // Note: Solutions are always total global values (natural distribution makes little sense for the solution)
813  dXdX = parallel_context->localNorm(ddX);
814  dXdX *= dXdX;
815 
816  if ( rtolf.at(1) > 0.0 ) {
817  // we compute a relative error norm
818  if ( ( RRT + internalForcesEBENorm.at(1) ) > nrsolver_ERROR_NORM_SMALL_NUM ) {
819  forceErr = sqrt( forceErr / ( RRT + internalForcesEBENorm.at(1) ) );
820  } else {
821  forceErr = sqrt(forceErr); // absolute norm as last resort
822  }
823  if ( fabs(forceErr) > rtolf.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
824  errorOutOfRange = true;
825  }
826  if ( fabs(forceErr) > rtolf.at(1) ) {
827  answer = false;
828  }
829 
830  if ( engngModel->giveProblemScale() == macroScale ) {
831  OOFEM_LOG_INFO(" %-15e", forceErr);
832  }
833 
834  if ( this->constrainedNRFlag ) {
835  // store the errors from the current iteration for use in the next
836  forceErrVec.at(1) = forceErr;
837  }
838  }
839 
840  if ( rtold.at(1) > 0.0 ) {
841  // compute displacement error
842  // err is relative displacement change
843  if ( dXX > nrsolver_ERROR_NORM_SMALL_NUM ) {
844  dispErr = sqrt(dXdX / dXX);
845  } else {
846  dispErr = sqrt(dXdX);
847  }
848  if ( fabs(dispErr) > rtold.at(1) * NRSOLVER_MAX_REL_ERROR_BOUND ) {
849  errorOutOfRange = true;
850  }
851  if ( fabs(dispErr) > rtold.at(1) ) {
852  answer = false;
853  }
854 
855  if ( engngModel->giveProblemScale() == macroScale ) {
856  OOFEM_LOG_INFO(" %-15e", dispErr);
857  }
858  }
859 
860  if ( engngModel->giveProblemScale() == macroScale ) {
861  OOFEM_LOG_INFO("\n");
862  }
863  } // end default case (all dofs contributing)
864 
865  return answer;
866 }
867 } // end namespace oofem
LinSystSolverType
The values of this type should be related not to specific solvers, but more to specific packages that...
virtual SparseLinearSystemNM * giveLinearSolver()
Constructs (if necessary) and returns a linear solver.
Definition: nrsolver.C:390
The representation of EngngModel default unknown numbering.
#define _IFT_NRSolver_linesearch
Definition: nrsolver.h:62
#define NM_Success
Numerical method exited with success.
Definition: nmstatus.h:47
void applyConstraintsToStiffness(SparseMtrx &k)
Definition: nrsolver.C:454
Class and object Domain.
Definition: domain.h:115
problemScale giveProblemScale()
Returns scale in multiscale simulation.
Definition: engngm.h:418
int giveGlobalNumber() const
Definition: dofmanager.h:501
double constrainedNRalpha
Scale factor for dX, dX_new = alpha * dX.
Definition: nrsolver.h:143
bool isLocal(DofManager *dman)
virtual IRResultType initializeFrom(InputRecord *ir)
Definition: nummet.h:101
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition: domain.h:432
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
#define _IFT_NRSolver_manrmsteps
Definition: nrsolver.h:57
void initPrescribedEqs()
Initiates prescribed equations.
Definition: nrsolver.C:420
int numberOfPrescribedDofs
number of prescribed displacement
Definition: nrsolver.h:113
This class implements Newton-Raphson Method, derived from abstract NumericalMethod class for solving ...
Definition: nrsolver.h:95
#define _IFT_NRSolver_forceScaleDofs
Definition: nrsolver.h:71
IntArray prescribedDofs
Array of pairs identifying prescribed dofs (node, dof)
Definition: nrsolver.h:123
LineSearchNM * giveLineSearchSolver()
Constructs and returns a line search solver.
Definition: nrsolver.C:410
void zero()
Sets all component to zero.
Definition: intarray.C:52
ExportModuleManager * giveExportModuleManager()
Returns receiver&#39;s export module manager.
Definition: engngm.h:758
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
void createVecGlobal(Vec *answer) const
Creates a global vector that fits the instance of this matrix.
This base class is an abstraction for all numerical methods solving sparse linear system of equations...
#define _IFT_NRSolver_ddm
Definition: nrsolver.h:59
void clear()
Clears receiver (zero size).
Definition: floatarray.h:206
REGISTER_SparseNonLinearSystemNM(CylindricalALM)
Definition: calmls.C:58
#define _IFT_NRSolver_calcstiffbeforeres
Definition: nrsolver.h:66
#define _IFT_NRSolver_rtolv
Definition: nrsolver.h:63
virtual IRResultType initializeFrom(InputRecord *ir)
Definition: nrsolver.C:103
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
double giveTargetTime()
Returns target time.
Definition: timestep.h:146
FloatArray rtold
Relative iterative displacement change tolerance for each group.
Definition: nrsolver.h:150
void incrementStateCounter()
Updates solution state counter.
Definition: timestep.h:190
void doOutput(TimeStep *tStep, bool substepFlag=false)
Writes the output.
Base class for dof managers.
Definition: dofmanager.h:113
std::vector< std::unique_ptr< DofManager > > & giveDofManagers()
Definition: domain.h:400
bool lsFlag
Flag indicating whether to use line-search.
Definition: nrsolver.h:135
int giveNumber()
Returns domain number.
Definition: domain.h:266
std::unique_ptr< LineSearchNM > linesearchSolver
Line search solver.
Definition: nrsolver.h:137
virtual double & at(int i, int j)=0
Returns coefficient at position (i,j).
#define _IFT_NRSolver_maxiter
Definition: nrsolver.h:54
std::unique_ptr< SparseLinearSystemNM > linSolver
linear system solver
Definition: nrsolver.h:107
unsigned long NM_Status
Mask defining NumMetod Status; which can be asked after finishing computation by Numerical Method...
Definition: nmstatus.h:44
#define OOFEM_LOG_DEBUG(...)
Definition: logger.h:128
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
std::map< int, double > dg_forceScale
Optional user supplied scale of forces used in convergence check.
Definition: nrsolver.h:157
LinSystSolverType solverType
linear system solver ID
Definition: nrsolver.h:109
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Sets receiver to be a - b.
Definition: floatarray.C:341
int constrainedNRminiter
Minimum number of iterations before constraint is activated.
Definition: nrsolver.h:145
double giveTimeIncrement()
Returns solution step associated time increment.
Definition: timestep.h:150
bool isTheFirstStep()
Check if receiver is first step.
Definition: timestep.C:134
void incrementSubStepNumber()
Increments receiver&#39;s substep number.
Definition: timestep.h:194
#define NM_NoSuccess
Numerical method failed to solve problem.
Definition: nmstatus.h:48
Domain * domain
Pointer to domain.
Definition: nummet.h:84
std::vector< std::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition: domain.h:322
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
#define OOFEM_ERROR(...)
Definition: error.h:61
double minStepLength
Definition: nrsolver.h:101
void applyConstraintsToLoadIncrement(int nite, const SparseMtrx &k, FloatArray &R, referenceLoadInputModeType rlm, TimeStep *tStep)
Definition: nrsolver.C:498
void clear()
Clears the array (zero size).
Definition: intarray.h:177
double computeSquaredNorm() const
Computes the square of the norm.
Definition: floatarray.C:846
DofIDItem
Type representing particular dof type.
Definition: dofiditem.h:86
virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d)
Updates components mapped to numerical method if necessary during solution process.
Definition: engngm.C:1485
The reference incremental load vector is defined as totalLoadVector assembled at given time...
FloatArray rtolf
Relative unbalanced force tolerance for each group.
Definition: nrsolver.h:148
virtual ParallelContext * giveParallelContext(int n)
Returns the parallel context corresponding to given domain (n) and unknown type Default implementatio...
Definition: engngm.C:1745
#define _IFT_NRSolver_miniterations
Definition: nrsolver.h:55
#define _IFT_NRSolver_rtolf
Definition: nrsolver.h:64
#define _IFT_NRSolver_ddv
Definition: nrsolver.h:60
referenceLoadInputModeType
The following parameter allows to specify how the reference load vector is obtained from given totalL...
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
#define _IFT_NRSolver_maxinc
Definition: nrsolver.h:69
Function * giveFunction(int n)
Service for accessing particular domain load time function.
Definition: domain.C:268
FloatArray forceErrVecOld
Definition: nrsolver.h:154
#define NM_None
Definition: nmstatus.h:46
virtual ~NRSolver()
Definition: nrsolver.C:97
Initializes the variable VERBOSE, in order to get a few intermediate messages on screen: beginning an...
Class representing vector of real numbers.
Definition: floatarray.h:82
SparseLinearSystemNM * createSparseLinSolver(LinSystSolverType st, Domain *d, EngngModel *m)
Creates new instance of SparseLinearSystemNM corresponding to given type.
Definition: classfactory.C:120
bool mCalcStiffBeforeRes
Flag indicating if the stiffness should be evaluated before the residual in the first iteration...
Definition: nrsolver.h:139
virtual NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, FloatArray &X, FloatArray &dX, FloatArray &F, const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, int &nite, TimeStep *)
Solves the given sparse linear system of equations .
Definition: nrsolver.C:202
IRResultType initializeFrom(InputRecord *ir)
Element is local, there are no contributions from other domains to this element.
Definition: element.h:101
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
virtual NM_Status solve(FloatArray &r, FloatArray &dr, FloatArray &F, FloatArray &R, FloatArray *R0, IntArray &eqnmask, double lambda, double &etaValue, LS_status &status, TimeStep *tStep)
Solves the line search optimization problem in the form of , The aim is to find so that the has dec...
Definition: linesearch.C:55
virtual IRResultType initializeFrom(InputRecord *ir)
Definition: linesearch.C:247
bool constrainedNRFlag
Flag indicating whether to use constrained Newton.
Definition: nrsolver.h:141
#define _IFT_NRSolver_forceScale
Definition: nrsolver.h:70
Class representing the general Input Record.
Definition: inputrecord.h:101
virtual void printState(FILE *outputStream)
Prints status message of receiver to output stream.
Definition: nrsolver.C:558
#define _IFT_NRSolver_lstype
Definition: nrsolver.h:58
#define NRSOLVER_MAX_REL_ERROR_BOUND
Definition: nrsolver.C:61
This class provides an communication context for distributed memory parallelism.
FloatArray forceErrVec
Definition: nrsolver.h:153
Dof * giveDofWithID(int dofID) const
Returns DOF with given dofID; issues error if not present.
Definition: dofmanager.C:119
IntArray prescribedEqs
Array of prescribed equations.
Definition: nrsolver.h:129
nrsolver_ModeType NR_OldMode
Definition: nrsolver.h:102
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
int giveMaxDofID()
Gives the current maximum dof ID used.
Definition: domain.h:600
void times(double s)
Multiplies receiver with scalar.
Definition: floatarray.C:818
nrsolver_ModeType NR_Mode
Definition: nrsolver.h:102
double accumulate(double local)
Accumulates the global value.
ClassFactory & classFactory
Definition: classfactory.C:59
std::string __DofIDItemToString(DofIDItem _value)
Definition: cltypes.C:330
bool prescribedDofsFlag
Flag indicating that some dofs are controlled under displacement control.
Definition: nrsolver.h:120
int giveEquationNumber(const UnknownNumberingScheme &s)
Returns equation number of receiver for given equation numbering scheme.
Definition: dof.C:56
std::vector< std::unique_ptr< Element > > & giveElements()
Definition: domain.h:279
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
#define _IFT_NRSolver_rtold
Definition: nrsolver.h:65
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
SparseMtrx::SparseMtrxVersionType smConstraintVersion
sparse matrix version, used to control constrains application to stiffness
Definition: nrsolver.h:111
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
Node * giveNode(int n)
Service for accessing particular domain node.
Definition: domain.h:371
the oofem namespace is to define a context or scope in which all oofem names are defined.
FloatArray lastReactions
Computed reactions. They are stored in order to print them in printState method.
Definition: nrsolver.h:133
Domain * giveDomain(int n)
Service for accessing particular problem domain.
Definition: engngm.C:1720
int prescribedDisplacementTF
Load Time Function of prescribed values.
Definition: nrsolver.h:127
#define _IFT_NRSolver_ddfunc
Definition: nrsolver.h:61
#define IR_GIVE_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:69
Abstract class Dof represents Degree Of Freedom in finite element mesh.
Definition: dof.h:93
#define _IFT_NRSolver_minsteplength
Definition: nrsolver.h:56
#define _IFT_NRSolver_constrainedNRminiter
Definition: nrsolver.h:68
EngngModel * engngModel
Pointer to engineering model.
Definition: nummet.h:86
double localNorm(const FloatArray &src)
Norm for a locally distributed array.
virtual double evaluateAtTime(double t)
Returns the value of the function at given time.
Definition: function.C:76
bool prescribedEqsInitFlag
Flag indicating that prescribedEqs were initialized.
Definition: nrsolver.h:131
This class provides an sparse matrix interface to PETSc Matrices.
#define OOFEM_WARNING(...)
Definition: error.h:62
double maxIncAllowed
Definition: nrsolver.h:159
Class representing solution step.
Definition: timestep.h:80
This base class is an abstraction for all numerical methods solving sparse nonlinear system of equati...
void add(const FloatArray &src)
Adds array src to receiver.
Definition: floatarray.C:156
bool checkConvergence(FloatArray &RT, FloatArray &F, FloatArray &rhs, FloatArray &ddX, FloatArray &X, double RRT, const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange)
Determines whether or not the solution has reached convergence.
Definition: nrsolver.C:580
#define nrsolver_ERROR_NORM_SMALL_NUM
Definition: nrsolver.C:60
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631
SparseMtrxVersionType giveVersion()
Return receiver version.
Definition: sparsemtrx.h:94
FloatArray prescribedDofsValues
Array of prescribed values.
Definition: nrsolver.h:125
This base class is an abstraction/implementation for numerical method solving line search optimizatio...
Definition: linesearch.h:60

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:30 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011