OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
staggeredsolver.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 "staggeredsolver.h"
36 #include "timestep.h"
37 #include "classfactory.h"
38 #include "exportmodulemanager.h"
39 #include "engngm.h"
40 #include "domain.h"
41 #include "dofmanager.h"
42 #include "element.h"
44 #include "dof.h"
45 #include "mathfem.h"
46 
47 namespace oofem {
48 
49 #define ERROR_NORM_SMALL_NUM 1.e-6
50 #define MAX_REL_ERROR_BOUND 1.e20
51 
53 
54 
55 int CustomEquationNumbering :: giveDofEquationNumber(Dof* dof) const
56 {
57  DofIDItem id = dof->giveDofID();
58  //printf("asking for num %d \n", (int)id);
59  if ( this->dofIdArray.contains( (int)id ) ) {
60  return prescribed ? dof->__givePrescribedEquationNumber() : dof->__giveEquationNumber();
61  } else {
62  return 0;
63  }
64 }
65 
66 
68  prescribed(false), numEqs(0), numPresEqs(0), dofIdArray(0)
69 {
70 }
71 
72 
74 {
75  this->UnknownNumberingSchemeList.resize(0);
76 }
77 
78 
81 {
82  IRResultType result; // Required by IR_GIVE_FIELD macro
83 
84  result = NRSolver ::initializeFrom(ir);
85  if ( result != IRRT_OK ) {
86  return result;
87  }
88 
91 
92  int numDofIdGroups = idPos.giveSize()/2;
93  this->UnknownNumberingSchemeList.resize(numDofIdGroups);
94  for ( int i = 0; i < numDofIdGroups; i++ ) {
95  int sz = idPos.at(i*2 + 2) - idPos.at(i*2 + 1) + 1;
96  IntArray idList(sz);
97  for ( int j = 0; j < sz; j++) {
98  int pos = idPos.at(i*2 + 1) + j;
99  idList[j] = this->totalIdList.at(pos);
100  }
101  this->UnknownNumberingSchemeList[i].setDofIdArray(idList);
102  }
103  return IRRT_OK;
104 }
105 
106 
107 DofGrouping :: DofGrouping(const std :: vector< CustomEquationNumbering > &numberings, Domain *d):
108  stiffnessMatrixList(numberings.size()),
109  fIntList(numberings.size()),
110  fExtList(numberings.size()),
111  locArrayList(numberings.size()),
112  X(numberings.size()),
113  dX(numberings.size()),
114  ddX(numberings.size())
115 {
116  for ( int dG = 0; dG < (int)numberings.size(); dG++ ) {
117  this->giveTotalLocationArray(locArrayList[dG], numberings[dG], d);
118  }
119 }
120 
121 
122 void
124 {
125  IntArray nodalArray, ids, locationArray;
126  locationArray.clear();
127 
128  for ( auto &dman : d->giveDofManagers() ) {
129  dman->giveCompleteLocationArray(nodalArray, s);
130  locationArray.followedBy(nodalArray);
131  }
132  for ( auto &elem : d->giveElements() ) {
133  for ( int i = 1; i <= elem->giveNumberOfInternalDofManagers(); i++ ) {
134  elem->giveInternalDofManDofIDMask(i, ids);
135  elem->giveInternalDofManager(i)->giveLocationArray(ids, nodalArray, s);
136  locationArray.followedBy(nodalArray);
137  }
138  }
139 
140  IntArray nonZeroMask;
141  nonZeroMask.findNonzeros(locationArray);
142 
143  condensedLocationArray.resize(nonZeroMask.giveSize());
144  for ( int i = 1; i <= nonZeroMask.giveSize(); i++ ) {
145  condensedLocationArray.at(i) = locationArray.at( nonZeroMask.at(i) );
146  }
147 }
148 
149 
150 NM_Status
152  FloatArray &Xtotal, FloatArray &dXtotal, FloatArray &F,
153  const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm,
154  int &nite, TimeStep *tStep)
155 
156 {
157  // residual, iteration increment of solution, total external force
158  FloatArray RHS, rhs, ddXtotal, RT;
159  double RRTtotal;
160  int neq = Xtotal.giveSize();
161  NM_Status status;
162  bool converged, errorOutOfRangeFlag;
163  ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
164 
165  if ( engngModel->giveProblemScale() == macroScale ) {
166  OOFEM_LOG_INFO("StaggeredSolver: Iteration");
167  if ( rtolf.at(1) > 0.0 ) {
168  OOFEM_LOG_INFO(" ForceError");
169  }
170  if ( rtold.at(1) > 0.0 ) {
171  OOFEM_LOG_INFO(" DisplError");
172  }
173  OOFEM_LOG_INFO("\n----------------------------------------------------------------------------\n");
174  }
175 
176  l = 1.0;
177  status = NM_None;
178  this->giveLinearSolver();
179 
180  // compute total load R = R+R0
181  RT = R;
182  if ( R0 ) {
183  RT.add(* R0);
184  }
185 
186  RRTtotal = parallel_context->localNorm(RT);
187  RRTtotal *= RRTtotal;
188 
189  ddXtotal.resize(neq);
190  ddXtotal.zero();
191 
192  // Fetch the matrix before evaluating internal forces.
193  // This is intentional, since its a simple way to drastically increase convergence for nonlinear problems.
194  // (This old tangent is just used)
195  // This improves convergence for many nonlinear problems, but not all. It may actually
196  // cause divergence for some nonlinear problems. Therefore a flag is used to determine if
197  // the stiffness should be evaluated before the residual (default yes). /ES
198 
199  DofGrouping dg(this->UnknownNumberingSchemeList, this->domain);
200 
201  // Compute external forces
202  int numDofIdGroups = (int)this->UnknownNumberingSchemeList.size();
203  FloatArray RRT(numDofIdGroups);
204  for ( int dG = 0; dG < numDofIdGroups; dG++ ) {
205  dg.fExtList[dG].beSubArrayOf( RT, dg.locArrayList[dG] );
206  RRT(dG) = dg.fExtList[dG].computeSquaredNorm();
207  }
208 
209  for (int nStaggeredIter = 0;; ++nStaggeredIter) {
210 
211  // Staggered iterations
212  for ( int dG = 0; dG < (int)this->UnknownNumberingSchemeList.size(); dG++ ) {
213  OOFEM_LOG_INFO("\nSolving for dof group %d \n", dG+1);
214 
215  engngModel->updateComponent(tStep, NonLinearLhs, domain);
216  dg.stiffnessMatrixList[dG].reset(k.giveSubMatrix( dg.locArrayList[dG], dg.locArrayList[dG]));
217 
218  if ( this->prescribedDofsFlag ) {
219  if ( !prescribedEqsInitFlag ) {
220  this->initPrescribedEqs();
221  }
222  applyConstraintsToStiffness(k);
223  }
224 
225  for (nite = 0;; ++nite) {
226  // Compute the residual
227  engngModel->updateComponent(tStep, InternalRhs, domain);
228  RHS.beDifferenceOf(RT, F);
229 
230  dg.fIntList[dG].beSubArrayOf( F, dg.locArrayList[dG] );
231  rhs.beDifferenceOf(dg.fExtList[dG], dg.fIntList[dG]);
232 
233  RHS.zero();
234  RHS.assemble(rhs, dg.locArrayList[dG]);
235 
236 
237  if ( this->prescribedDofsFlag ) {
238  this->applyConstraintsToLoadIncrement(nite, k, rhs, rlm, tStep);
239  }
240 
241  // convergence check
242  IntArray &idArray = UnknownNumberingSchemeList[dG].dofIdArray;
243  converged = this->checkConvergenceDofIdArray(RT, F, RHS, ddXtotal, Xtotal, RRTtotal, internalForcesEBENorm, nite, errorOutOfRangeFlag, tStep, idArray);
244 
245 
246  if ( errorOutOfRangeFlag ) {
247  status = NM_NoSuccess;
248  OOFEM_WARNING("Divergence reached after %d iterations", nite);
249  break;
250  } else if ( converged && ( nite >= minIterations ) ) {
251  status = NM_Success;
252  break;
253  } else if ( nite >= nsmax ) {
254  OOFEM_LOG_DEBUG("Maximum number of iterations reached\n");
255  break;
256  }
257 
258  if ( nite > 0 || !mCalcStiffBeforeRes ) {
259  if ( NR_Mode == nrsolverFullNRM || ( NR_Mode == nrsolverAccelNRM && (nite % MANRMSteps) == 0 ) ) {
260  engngModel->updateComponent(tStep, NonLinearLhs, domain);
261  dg.stiffnessMatrixList[dG].reset(k.giveSubMatrix( dg.locArrayList[dG], dg.locArrayList[dG]));
262  applyConstraintsToStiffness(*dg.stiffnessMatrixList[dG]);
263  }
264  }
265 
266  if ( ( nite == 0 ) && ( deltaL < 1.0 ) ) { // deltaL < 1 means no increment applied, only equilibrate current state
267  rhs.zero();
268  R.zero();
269  dg.ddX[dG] = rhs;
270  } else {
271  status = linSolver->solve(*dg.stiffnessMatrixList[dG], rhs, dg.ddX[dG]);
272  }
273 
274  //
275  // update solution
276  //
277  if ( this->lsFlag && ( nite > 0 ) ) { // Why not nite == 0 ?
278  // line search
279  LineSearchNM :: LS_status LSstatus;
280  double eta;
281  this->giveLineSearchSolver()->solve( dg.X[dG], dg.ddX[dG], dg.fIntList[dG], dg.fExtList[dG], R0, prescribedEqs, 1.0, eta, LSstatus, tStep);
282  } else if ( this->constrainedNRFlag && ( nite > this->constrainedNRminiter ) ) {
283  if ( this->forceErrVec.computeSquaredNorm() > this->forceErrVecOld.computeSquaredNorm() ) {
284  OOFEM_LOG_INFO("Constraining increment to be %e times full increment...\n", this->constrainedNRalpha);
285  dg.ddX[dG].times(this->constrainedNRalpha);
286  }
287  }
288  dg.X[dG].add(dg.ddX[dG]);
289  dg.dX[dG].add(dg.ddX[dG]);
290 
291 
292  // Update total solution (containing all dofs)
293  Xtotal.assemble(dg.ddX[dG], dg.locArrayList[dG]);
294  dXtotal.assemble(dg.ddX[dG], dg.locArrayList[dG]);
295  ddXtotal.zero();
296  ddXtotal.assemble(dg.ddX[dG], dg.locArrayList[dG]);
297 
298  tStep->incrementStateCounter(); // update solution state counter
299  tStep->incrementSubStepNumber();
300 
301  engngModel->giveExportModuleManager()->doOutput(tStep, true);
302  }
303  }
304 
305 
306  OOFEM_LOG_INFO("\nStaggered iteration (all dof id's) \n");
307 
308  // Check convergence of total system
309  RHS.beDifferenceOf(RT, F);
310  converged = this->checkConvergence(RT, F, RHS, ddXtotal, Xtotal, RRTtotal, internalForcesEBENorm, nStaggeredIter, errorOutOfRangeFlag);
311  if ( converged && ( nStaggeredIter >= minIterations ) ) {
312  break;
313  }
314  }
315 
316  // Modify Load vector to include "quasi reaction"
317  if ( R0 ) {
318  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
319  R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R0->at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) );
320  }
321  } else {
322  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
323  R.at( prescribedEqs.at(i) ) = F.at( prescribedEqs.at(i) ) - R.at( prescribedEqs.at(i) );
324  }
325  }
326 
327  this->lastReactions.resize(numberOfPrescribedDofs);
328 
329 #ifdef VERBOSE
330  if ( numberOfPrescribedDofs ) {
331  // print quasi reactions if direct displacement control used
332  OOFEM_LOG_INFO("\n");
333  OOFEM_LOG_INFO("StaggeredSolver: Quasi reaction table \n");
334  OOFEM_LOG_INFO("StaggeredSolver: Node Dof Displacement Force\n");
335  double reaction;
336  for ( int i = 1; i <= numberOfPrescribedDofs; i++ ) {
337  reaction = R->at( prescribedEqs.at(i) );
338  if ( R0 ) {
339  reaction += R0->at( prescribedEqs.at(i) );
340  }
341  lastReactions.at(i) = reaction;
342  OOFEM_LOG_INFO("StaggeredSolver: %-15d %-15d %-+15.5e %-+15.5e\n", prescribedDofs.at(2 * i - 1), prescribedDofs.at(2 * i),
343  X.at( prescribedEqs.at(i) ), reaction);
344  }
345  OOFEM_LOG_INFO("\n");
346  }
347 #endif
348 
349  return status;
350 }
351 
352 
353 //copied from nrsolver
354 
355 bool
357  double RRT, const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange, TimeStep *tStep, IntArray &dofIdArray)
358 {
359  double forceErr, dispErr;
360  FloatArray dg_forceErr, dg_dispErr, dg_totalLoadLevel, dg_totalDisp;
361  bool answer;
363  ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
364 
365  /*
366  * The force errors are (if possible) evaluated as relative errors.
367  * If the norm of applied load vector is zero (one may load by temperature, etc)
368  * then the norm of reaction forces is used in relative norm evaluation.
369  *
370  * Note: This is done only when all dofs are included (nccdg = 0). Not implemented if
371  * multiple convergence criteria are used.
372  *
373  */
374 
375  answer = true;
376  errorOutOfRange = false;
377 
378  // Store the errors associated with the dof groups
379  if ( this->constrainedNRFlag ) {
380  this->forceErrVecOld = this->forceErrVec; // copy the old values
381  this->forceErrVec.resize( internalForcesEBENorm.giveSize() );
382  forceErrVec.zero();
383  }
384 
385  if ( internalForcesEBENorm.giveSize() > 1 ) { // Special treatment when just one norm is given; No grouping
386  int nccdg = this->domain->giveMaxDofID();
387  // Keeps tracks of which dof IDs are actually in use;
388  IntArray idsInUse(nccdg);
389  idsInUse.zero();
390  // zero error norms per group
391  dg_forceErr.resize(nccdg);
392  dg_forceErr.zero();
393  dg_dispErr.resize(nccdg);
394  dg_dispErr.zero();
395  dg_totalLoadLevel.resize(nccdg);
396  dg_totalLoadLevel.zero();
397  dg_totalDisp.resize(nccdg);
398  dg_totalDisp.zero();
399  // loop over dof managers
400  for ( auto &dofman : domain->giveDofManagers() ) {
401  if ( !parallel_context->isLocal(dofman.get()) ) {
402  continue;
403  }
404 
405  // loop over individual dofs
406  for ( Dof *dof: *dofman ) {
407  if ( !dof->isPrimaryDof() ) {
408  continue;
409  }
410  int eq = dof->giveEquationNumber(dn);
411  int dofid = dof->giveDofID();
412  if ( !eq ) {
413  continue;
414  }
415 
416  dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
417  dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
418  dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
419  dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
420  idsInUse.at(dofid) = 1;
421  } // end loop over DOFs
422  } // end loop over dof managers
423 
424  // loop over elements and their DOFs
425  for ( auto &elem : domain->giveElements() ) {
426  if ( elem->giveParallelMode() != Element_local ) {
427  continue;
428  }
429 
430  // loop over element internal Dofs
431  for ( int idofman = 1; idofman <= elem->giveNumberOfInternalDofManagers(); idofman++ ) {
432  DofManager *dofman = elem->giveInternalDofManager(idofman);
433  // loop over individual dofs
434  for ( Dof *dof: *dofman ) {
435  if ( !dof->isPrimaryDof() ) {
436  continue;
437  }
438  int eq = dof->giveEquationNumber(dn);
439  int dofid = dof->giveDofID();
440 
441  if ( !eq ) {
442  continue;
443  }
444 
445  dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
446  dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
447  dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
448  dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
449  idsInUse.at(dofid) = 1;
450  } // end loop over DOFs
451  } // end loop over element internal dofmans
452  } // end loop over elements
453 
454  // loop over boundary conditions and their internal DOFs
455  for ( auto &bc : domain->giveBcs() ) {
456  // loop over element internal Dofs
457  for ( int idofman = 1; idofman <= bc->giveNumberOfInternalDofManagers(); idofman++ ) {
458  DofManager *dofman = bc->giveInternalDofManager(idofman);
459  // loop over individual dofs
460  for ( Dof *dof: *dofman ) {
461  if ( !dof->isPrimaryDof() ) {
462  continue;
463  }
464  int eq = dof->giveEquationNumber(dn);
465  int dofid = dof->giveDofID();
466 
467  if ( !eq ) {
468  continue;
469  }
470 
471  dg_forceErr.at(dofid) += rhs.at(eq) * rhs.at(eq);
472  dg_dispErr.at(dofid) += ddX.at(eq) * ddX.at(eq);
473  dg_totalLoadLevel.at(dofid) += RT.at(eq) * RT.at(eq);
474  dg_totalDisp.at(dofid) += X.at(eq) * X.at(eq);
475  idsInUse.at(dofid) = 1;
476  } // end loop over DOFs
477  } // end loop over element internal dofmans
478  } // end loop over elements
479 
480  // exchange individual partition contributions (simultaneously for all groups)
481  FloatArray collectiveErr(nccdg);
482  parallel_context->accumulate(dg_forceErr, collectiveErr);
483  dg_forceErr = collectiveErr;
484  parallel_context->accumulate(dg_dispErr, collectiveErr);
485  dg_dispErr = collectiveErr;
486  parallel_context->accumulate(dg_totalLoadLevel, collectiveErr);
487  dg_totalLoadLevel = collectiveErr;
488  parallel_context->accumulate(dg_totalDisp, collectiveErr);
489  dg_totalDisp = collectiveErr;
490 
491  OOFEM_LOG_INFO("StaggeredSolver: %-5d", nite);
492  //bool zeroNorm = false;
493  // loop over dof groups and check convergence individually
494  for ( int dg = 1; dg <= nccdg; dg++ ) {
495  bool zeroFNorm = false, zeroDNorm = false;
496  // 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)
497  if ( !idsInUse.at(dg) ) {
498  continue;
499  }
500 
501  if ( dofIdArray.giveSize() && !dofIdArray.contains(dg) ) {
502  continue;
503  }
504 
505 
506  OOFEM_LOG_INFO( " %s:", __DofIDItemToString( ( DofIDItem ) dg ).c_str() );
507 
508  if ( rtolf.at(1) > 0.0 ) {
509  // compute a relative error norm
510  if ( ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) > ERROR_NORM_SMALL_NUM ) {
511  forceErr = sqrt( dg_forceErr.at(dg) / ( dg_totalLoadLevel.at(dg) + internalForcesEBENorm.at(dg) ) );
512  } else {
513  // If both external forces and internal ebe norms are zero, then the residual must be zero.
514  //zeroNorm = true; // Warning about this afterwards.
515  zeroFNorm = true;
516  forceErr = sqrt( dg_forceErr.at(dg) );
517  }
518 
519  if ( forceErr > rtolf.at(1) * MAX_REL_ERROR_BOUND ) {
520  errorOutOfRange = true;
521  }
522  if ( forceErr > rtolf.at(1) ) {
523  answer = false;
524  }
525  OOFEM_LOG_INFO(zeroFNorm ? " *%.3e" : " %.3e", forceErr);
526 
527  // Store the errors from the current iteration
528  if ( this->constrainedNRFlag ) {
529  forceErrVec.at(dg) = forceErr;
530  }
531  }
532 
533  if ( rtold.at(1) > 0.0 ) {
534  // compute displacement error
535  if ( dg_totalDisp.at(dg) > ERROR_NORM_SMALL_NUM ) {
536  dispErr = sqrt( dg_dispErr.at(dg) / dg_totalDisp.at(dg) );
537  } else {
539  //zeroNorm = true; // Warning about this afterwards.
540  //zeroDNorm = true;
541  dispErr = sqrt( dg_dispErr.at(dg) );
542  }
543  if ( dispErr > rtold.at(1) * MAX_REL_ERROR_BOUND ) {
544  errorOutOfRange = true;
545  }
546  if ( dispErr > rtold.at(1) ) {
547  answer = false;
548  }
549  OOFEM_LOG_INFO(zeroDNorm ? " *%.3e" : " %.3e", dispErr);
550  }
551  }
552  OOFEM_LOG_INFO("\n");
553  //if ( zeroNorm ) OOFEM_WARNING("Had to resort to absolute error measure (marked by *)");
554  } else { // No dof grouping
555  double dXX, dXdX;
556 
557  if ( engngModel->giveProblemScale() == macroScale ) {
558  OOFEM_LOG_INFO("StaggeredSolver: %-15d", nite);
559  } else {
560  OOFEM_LOG_INFO(" StaggeredSolver: %-15d", nite);
561  }
562 
563  forceErr = parallel_context->localNorm(rhs);
564  forceErr *= forceErr;
565  dXX = parallel_context->localNorm(X);
566  dXX *= dXX; // Note: Solutions are always total global values (natural distribution makes little sense for the solution)
567  dXdX = parallel_context->localNorm(ddX);
568  dXdX *= dXdX;
569 
570  if ( rtolf.at(1) > 0.0 ) {
571  // we compute a relative error norm
572  if ( ( RRT + internalForcesEBENorm.at(1) ) > ERROR_NORM_SMALL_NUM ) {
573  forceErr = sqrt( forceErr / ( RRT + internalForcesEBENorm.at(1) ) );
574  } else {
575  forceErr = sqrt(forceErr); // absolute norm as last resort
576  }
577  if ( fabs(forceErr) > rtolf.at(1) * MAX_REL_ERROR_BOUND ) {
578  errorOutOfRange = true;
579  }
580  if ( fabs(forceErr) > rtolf.at(1) ) {
581  answer = false;
582  }
583  OOFEM_LOG_INFO(" %-15e", forceErr);
584 
585  if ( this->constrainedNRFlag ) {
586  // store the errors from the current iteration for use in the next
587  forceErrVec.at(1) = forceErr;
588  }
589  }
590 
591  if ( rtold.at(1) > 0.0 ) {
592  // compute displacement error
593  // err is relative displacement change
594  if ( dXX > ERROR_NORM_SMALL_NUM ) {
595  dispErr = sqrt(dXdX / dXX);
596  } else {
597  dispErr = sqrt(dXdX);
598  }
599  if ( fabs(dispErr) > rtold.at(1) * MAX_REL_ERROR_BOUND ) {
600  errorOutOfRange = true;
601  }
602  if ( fabs(dispErr) > rtold.at(1) ) {
603  answer = false;
604  }
605  OOFEM_LOG_INFO(" %-15e", dispErr);
606  }
607 
608  OOFEM_LOG_INFO("\n");
609  } // end default case (all dofs contributing)
610 
611  return answer;
612 }
613 
614 } // end namespace oofem
615 
bool contains(int value) const
Definition: intarray.h:283
std::vector< std::unique_ptr< SparseMtrx > > stiffnessMatrixList
The representation of EngngModel default unknown numbering.
#define NM_Success
Numerical method exited with success.
Definition: nmstatus.h:47
Class and object Domain.
Definition: domain.h:115
std::vector< CustomEquationNumbering > UnknownNumberingSchemeList
bool isLocal(DofManager *dman)
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
This class implements Newton-Raphson Method, derived from abstract NumericalMethod class for solving ...
Definition: nrsolver.h:95
StaggeredSolver(Domain *d, EngngModel *m)
void zero()
Sets all component to zero.
Definition: intarray.C:52
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
REGISTER_SparseNonLinearSystemNM(CylindricalALM)
Definition: calmls.C:58
std::vector< FloatArray > fIntList
virtual IRResultType initializeFrom(InputRecord *ir)
Definition: nrsolver.C:103
#define MAX_REL_ERROR_BOUND
void incrementStateCounter()
Updates solution state counter.
Definition: timestep.h:190
Base class for dof managers.
Definition: dofmanager.h:113
std::vector< std::unique_ptr< DofManager > > & giveDofManagers()
Definition: domain.h:400
bool checkConvergenceDofIdArray(FloatArray &RT, FloatArray &F, FloatArray &rhs, FloatArray &ddX, FloatArray &X, double RRT, const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange, TimeStep *tStep, IntArray &dofIdArray)
void findNonzeros(const IntArray &logical)
Finds all indices where the input array is nonzero.
Definition: intarray.C:206
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
virtual SparseMtrx * giveSubMatrix(const IntArray &rows, const IntArray &cols)
Definition: sparsemtrx.h:263
virtual IRResultType initializeFrom(InputRecord *ir)
DofGrouping(const std::vector< CustomEquationNumbering > &numberings, Domain *m)
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Sets receiver to be a - b.
Definition: floatarray.C:341
std::vector< FloatArray > fExtList
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
std::vector< FloatArray > ddX
#define _IFT_StaggeredSolver_DofIdList
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
void clear()
Clears the array (zero size).
Definition: intarray.h:177
DofIDItem
Type representing particular dof type.
Definition: dofiditem.h:86
Abstract base class allowing to control the way, how equations are assigned to individual DOFs...
referenceLoadInputModeType
The following parameter allows to specify how the reference load vector is obtained from given totalL...
std::vector< FloatArray > dX
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
#define ERROR_NORM_SMALL_NUM
#define NM_None
Definition: nmstatus.h:46
Class representing vector of real numbers.
Definition: floatarray.h:82
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
void giveTotalLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, Domain *d)
void assemble(const FloatArray &fe, const IntArray &loc)
Assembles the array fe (typically, the load vector of a finite element) into the receiver, using loc as location array.
Definition: floatarray.C:551
Class representing the general Input Record.
Definition: inputrecord.h:101
This class provides an communication context for distributed memory parallelism.
void followedBy(const IntArray &b, int allocChunk=0)
Appends array b at the end of receiver.
Definition: intarray.C:145
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
double accumulate(double local)
Accumulates the global value.
std::string __DofIDItemToString(DofIDItem _value)
Definition: cltypes.C:330
std::vector< std::unique_ptr< Element > > & giveElements()
Definition: domain.h:279
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
int giveSize() const
Definition: intarray.h:203
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
the oofem namespace is to define a context or scope in which all oofem names are defined.
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 .
#define IR_GIVE_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:69
std::vector< FloatArray > X
Abstract class Dof represents Degree Of Freedom in finite element mesh.
Definition: dof.h:93
Support struct to handle all the split up variables used during the solving step. ...
double localNorm(const FloatArray &src)
Norm for a locally distributed array.
#define OOFEM_WARNING(...)
Definition: error.h:62
Class representing solution step.
Definition: timestep.h:80
The staggered solver will perform Newton iterations on subsets of DofIDs, in a staggered manner...
#define _IFT_StaggeredSolver_DofIdListPositions
void add(const FloatArray &src)
Adds array src to receiver.
Definition: floatarray.C:156
std::vector< IntArray > locArrayList
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631

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:31 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011