OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
calmls.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 "calmls.h"
36 #include "verbose.h"
37 #include "timestep.h"
38 #include "floatmatrix.h"
39 #include "datastream.h"
40 #include "mathfem.h"
41 #include "element.h"
42 #include "classfactory.h"
43 #include "engngm.h"
44 // includes for HPC - not very clean (NumMethod knows what is "node" and "dof")
45 #include "node.h"
46 #include "dof.h"
47 #include "contextioerr.h"
48 #include "exportmodulemanager.h"
49 #include "parallelcontext.h"
50 #include "unknownnumberingscheme.h"
51 
52 namespace oofem {
53 #define CALM_RESET_STEP_REDUCE 0.25
54 #define CALM_TANGENT_STIFF_TRESHOLD 0.1
55 #define CALM_DEFAULT_NRM_TICKS 2
56 #define CALM_MAX_REL_ERROR_BOUND 1.e10
57 
59 
61  SparseNonLinearSystemNM(d, m), calm_HPCWeights(), calm_HPCIndirectDofMask(), calm_HPCDmanDofSrcArray(), ccDofGroups()
62 {
63  nsmax = 60; // default maximum number of sweeps allowed
64  numberOfRequiredIterations = 3;
65  //rtol = 10.E-3 ; // convergence tolerance
66  //Psi = 0.1; // displacement control on
67  Psi = 1.0; // load control on
68  solved = 0;
69  calm_NR_Mode = calm_NR_OldMode = calm_modifiedNRM;
70  calm_NR_ModeTick = -1; // do not swith to calm_NR_OldMode
71  calm_MANRMSteps = 0;
72 
73  //Bergan_k0 = 0.; // value used for computing Bergan's parameter
74  // of current stiffness.
75 
76  deltaL = -1.0;
77  // TangenStiffnessTreshold = 0.10;
78 
79  // Variables for Hyper Plane Control
80  calm_Control = calm_hpc_off; // HPControl is not default
81  // linesearch default off
82  lsFlag = 0;
83 
84  ls_tolerance = 0.40;
85  amplifFactor = 2.5;
86  maxEta = 8.5;
87  minEta = 0.2;
88 
89  // number of convergence_criteria dof groups, set to 0 (default behavior)
90  nccdg = 0;
91 
92  minIterations = 0;
93 
94  calm_hpc_init = 0;
95 
96  // Maximum number of restarts when convergence not reached during maxiter
97  maxRestarts = 4;
98 
99  parallel_context = engngModel->giveParallelContext( d->giveNumber() );
100 }
101 
102 
104 {
105 }
106 
107 
108 NM_Status
110  FloatArray &X, FloatArray &dX, FloatArray &F,
111  const FloatArray &internalForcesEBENorm, double &ReachedLambda, referenceLoadInputModeType rlm,
112  int &nite, TimeStep *tStep)
113 {
114  FloatArray rhs, deltaXt, deltaX_, dXm1, XInitial;
115  FloatArray ddX; // total increment of displacements in iteration
116  //double Bergan_k0 = 1.0, bk;
117  double XX, RR, RR0, XR, p = 0.0;
118  double deltaLambda, Lambda, eta, DeltaLambdam1, DeltaLambda = 0.0;
119  double drProduct = 0.0;
120  int neq = R.giveSize();
121  int irest = 0;
122  int HPsize, i, ind;
123  double _RR, _XX;
124  NM_Status status;
125  bool converged, errorOutOfRangeFlag;
126  // print iteration header
127 
128  OOFEM_LOG_INFO("CALMLS: Initial step length: %-15e\n", deltaL);
129  if ( nccdg == 0 ) {
130  OOFEM_LOG_INFO("CALMLS: Iteration LoadLevel ForceError DisplError \n");
131  OOFEM_LOG_INFO("----------------------------------------------------------------------------\n");
132  } else {
133  OOFEM_LOG_INFO("Iter LoadLevel ");
134  for ( i = 1; i <= nccdg; i++ ) {
135  OOFEM_LOG_INFO("ForceError(%02d) DisplError(%02d) ", i, i);
136  }
137 
138  OOFEM_LOG_INFO("\n__________________________________________________________\n");
139  }
140 
141  //
142  // Now smarter method is default:
143  // after convergence troubles for (calm_NR_ModeTick subsequent
144  // steps newly set calm_NR_Mode will be used. After the calm_NR_OldMode will be restored
145  //
146  if ( calm_NR_ModeTick == 0 ) {
148  }
149 
150  if ( calm_NR_ModeTick > 0 ) {
152  }
153 
154  XInitial = X;
155  ddX.resize(neq);
156  ddX.zero();
157  deltaXt.resize(neq);
158  deltaXt.zero();
159 
160  status = NM_None;
161  this->giveLinearSolver();
162 
163  // create HPC Map if needed
164  if ( calm_hpc_init ) {
165  this->convertHPCMap();
166  calm_hpc_init = 0;
167  }
168 
169  if ( R0 ) {
170  RR0 = parallel_context->localNorm(* R0);
171  RR0 *= RR0;
172  } else {
173  RR0 = 0.0;
174  }
175 
176  //
177  // A initial step (predictor)
178  //
179  //
180 
181  //
182  // A.2. We assume positive-definite (0)Kt (tangent stiffness mtrx).
183  //
184  RR = parallel_context->localNorm(R);
185  RR *= RR;
186 
187 restart:
188  //
189  // A.1. calculation of (0)VarRt
190  //
191  dX.zero();
192  //engngModel->updateComponent(tStep, InternalRhs, domain); // By not updating this, one obtains the old equilibrated tangent.
194  linSolver->solve(k, R, deltaXt);
195 
196  // If desired by the user, the solution is (slightly) perturbed, so that various symmetries can be broken.
197  // This is useful e.g. to trigger localization in a homogeneous material under uniform stress without
198  // the need to introduce material imperfections. The problem itself remains symmetric but the iterative
199  // solution is brought to a nonsymmetric state and it gets a chance to converge to a nonsymmetric solution.
200  // Parameters of the perturbation technique are specified by the user and by default no perturbation is done.
201  // Milan Jirasek
203 
204  if ( calm_Control == calm_hpc_off ) {
205  XX = parallel_context->localNorm(deltaXt);
206  XX *= XX;
207  p = sqrt(XX + Psi * Psi * RR);
208  } else if ( calm_Control == calm_hpc_on ) {
210  _XX = 0;
211  _RR = 0;
212  for ( i = 1; i <= HPsize; i++ ) {
213  if ( ( ind = calm_HPCIndirectDofMask.at(i) ) != 0 ) {
214  _XX += deltaXt.at(ind) * deltaXt.at(ind);
215  _RR += R.at(ind) * R.at(ind);
216  }
217  }
218 
219  // In case of paralllel analysis:
220  FloatArray collected_XXRR;
221  parallel_context->accumulate({_XX, _RR}, collected_XXRR);
222  _XX = collected_XXRR(0);
223  _RR = collected_XXRR(1);
224 
225  p = sqrt(_XX + Psi * Psi * _RR);
226  } else if ( calm_Control == calml_hpc ) {
228  p = 0.;
229  for ( i = 1; i <= HPsize; i++ ) {
230  if ( ( ind = calm_HPCIndirectDofMask.at(i) ) != 0 ) {
231  p += deltaXt.at(ind) * calm_HPCWeights.at(i);
232  }
233  }
234 
235  // In case of paralllel analysis:
237  }
238 
239  XR = parallel_context->localDotProduct(deltaXt, R);
240  /* XR is unscaled Bergan's param of current stiffness XR = deltaXt^T k deltaXt
241  * this is used to test whether k has negative or positive slope */
242 
243  Lambda = ReachedLambda;
244  DeltaLambda = deltaLambda = sgn(XR) * deltaL / p;
245  Lambda += DeltaLambda;
246  //
247  // A.3.
248  //
249 
250  rhs = R;
251  rhs.times(DeltaLambda);
252  if ( R0 ) {
253  rhs.add(* R0);
254  }
255  linSolver->solve(k, rhs, dX);
256  X.add(dX);
257 
258  nite = 0;
259 
260  // update solution state counter
261  tStep->incrementStateCounter();
263 
264  do {
265  nite++;
266  tStep->incrementSubStepNumber();
267 
268  dXm1 = dX;
269  DeltaLambdam1 = DeltaLambda;
270 
271  //
272  // B - iteration MNRM is used
273  //
274  // B.1. is ommited because MNRM is used instead of NRM.
275  //
276  if ( ( calm_NR_Mode == calm_fullNRM ) || ( ( calm_NR_Mode == calm_accelNRM ) && ( nite % calm_MANRMSteps == 0 ) ) ) {
277  //
278  // ALM with full NRM
279  //
280  // we assemble new tangent stiffness and compute new deltaXt
281  // internal state of elements is updated by previous calling
282  // InternalRhs
283  //
285  //
286  // compute deltaXt for i-th iteration
287  //
288  linSolver->solve(k, R, deltaXt);
289  }
290 
291  // B.2.
292  //
293 
294  rhs = R;
295  rhs.times(Lambda);
296  if ( R0 ) {
297  rhs.add(* R0);
298  }
299 
300  rhs.subtract(F);
301  deltaX_.resize(neq);
302  linSolver->solve(k, rhs, deltaX_);
303  eta = 1.0;
304  //
305  // B.3.
306  //
307  if ( this->computeDeltaLambda(deltaLambda, dX, deltaXt, deltaX_, R, RR, eta, deltaL, DeltaLambda, neq) ) {
308  irest++;
309  if ( irest <= maxRestarts ) {
310  // convergence problems
311  // there must be step restart followed by decrease of step length
312  // status |= NM_ForceRestart;
313  // reduce step length
315  if ( deltaL < minStepLength ) {
317  }
318 
319  // restore previous total displacement vector
320  X = XInitial;
321  // reset all changes fro previous equilibrium state
322  dX.zero();
323  // restore initial stiffness
325 
326  OOFEM_LOG_INFO("CALMLS: Iteration Reset ...\n");
327 
331  goto restart;
332  } else {
333  status = NM_NoSuccess;
334  OOFEM_ERROR("can't continue further");
335  }
336  }
337 
338  //
339  // B.4.+ B.5.
340  //
341 
342 
343  if ( this->lsFlag && ( nite != 1 ) ) {
344  //
345  // LINE SEARCH
346  //
347  this->do_lineSearch(X, XInitial, deltaX_, deltaXt,
348  dXm1, dX, ddX,
349  R, R0, F,
350  DeltaLambda, DeltaLambdam1, deltaLambda, Lambda, ReachedLambda,
351  RR, drProduct, tStep);
352  } else { // no line search
353  //
354  // update solution vectors
355  //
356  ddX.clear();
357  ddX.add(eta * deltaLambda, deltaXt);
358  ddX.add(eta, deltaX_);
359  dX = dXm1;
360  dX.add(ddX);
361  X = XInitial;
362  X.add(dX);
363 
364  drProduct = parallel_context->localNorm(ddX);
365  drProduct *= drProduct;
366 
367  tStep->incrementStateCounter(); // update solution state counter
368  //
369  // B.6.
370  //
371  DeltaLambda = DeltaLambdam1 + deltaLambda;
372  Lambda = ReachedLambda + DeltaLambda;
373 
374  tStep->incrementStateCounter(); // update solution state counter
376  }
377 
378  //
379  // B.7.
380  //
381  // convergence check
382  //
383 
384  converged = this->checkConvergence(R, R0, F, X, ddX, Lambda, RR0, RR, drProduct,
385  internalForcesEBENorm, nite, errorOutOfRangeFlag);
386  if ( ( nite >= nsmax ) || errorOutOfRangeFlag ) {
387  irest++;
388  if ( irest <= maxRestarts ) {
389  // convergence problems
390  // there must be step restart followed by decrease of step length
391  // status |= NM_ForceRestart;
392  // reduce step length
394  if ( deltaL < minStepLength ) {
396  }
397 
398  // restore previous total displacement vector
399  X = XInitial;
400  // reset all changes from previous equilibrium state
402  dX.zero();
403  // restore initial stiffness
405 
406  OOFEM_LOG_INFO("CALMLS: Iteration Reset ...\n");
407 
411  goto restart;
412  } else {
413  status = NM_NoSuccess;
414  OOFEM_WARNING("Convergence not reached after %d iterations", nsmax);
415  // exit(1);
416  break;
417  }
418  }
419 
420  // output of per iteration data
422  } while ( !converged || ( nite < minIterations ) );
423 
424  //
425  // update dofs,nodes,Elemms and print result
426  //
427 #ifdef VERBOSE
428  // printf ("\nCALM - step iteration finished") ;
429 #endif
430 
431  // Seems to be completely unused / Mikael
432 #if 0
433  /* compute Bergan's parameter of current stiffness */
434  double RDR = parallel_context->localDotProduct(* R, * dX);
435  double DR = parallel_context->localNorm(* dX);
436  bk = DeltaLambda * RDR / ( DR * DR );
437 
438  if ( tStep->giveNumber() == 1 ) {
439  // compute Bergan_k0
440  Bergan_k0 = bk;
441  } else {
442  bk = bk / Bergan_k0;
443  //if (fabs(bk) < CALM_TANGENT_STIFF_TRESHOLD) status |= NM_KeepTangent;
444  }
445 #endif
446 
447  /* we have computed Bergan's parameter -> you can adjust deltaL according
448  * to this value */
449  //
450  // there has been restart already - set nite to maxiter
451  //
452  // if (irest > 0) nite = nsmax;
453 
454  if ( nite > numberOfRequiredIterations ) {
456  } else {
457  deltaL = deltaL * sqrt( sqrt( ( double ) numberOfRequiredIterations / ( double ) nite ) );
458  }
459 
460  if ( deltaL > maxStepLength ) {
462  }
463 
464  if ( deltaL < minStepLength ) {
466  }
467 
468  OOFEM_LOG_INFO("CALMLS: Adjusted step length: %-15e\n", deltaL);
469 
470  status = NM_Success;
471  solved = 1;
472  ReachedLambda = Lambda;
473 
474  return status;
475 }
476 
477 bool
479  const FloatArray &X, const FloatArray &ddX,
480  double Lambda, double RR0, double RR, double drProduct,
481  const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange)
482 {
483  /*
484  * typedef std::set<DofID> __DofIDSet;
485  * std::list<__DofIDSet> __ccDofGroups;
486  * int nccdg; // number of Convergence Criteria Dof Groups
487  */
488  int _ng = nccdg;
489  double forceErr, dispErr;
490  FloatArray rhs; // residual of momentum balance eq (unbalanced nodal forces)
491  FloatArray dg_forceErr(nccdg), dg_dispErr(nccdg), dg_totalLoadLevel(nccdg), dg_totalDisp(nccdg);
492  bool answer;
494 
495  answer = true;
496  errorOutOfRange = false;
497 
498  // compute residual vector
499  rhs = R;
500  rhs.times(Lambda);
501  if ( R0 ) {
502  rhs.add(* R0);
503  }
504 
505  rhs.subtract(F);
506 
507  if ( _ng > 0 ) {
508  forceErr = dispErr = 0.0;
509  // zero error norms per group
510  dg_forceErr.zero();
511  dg_dispErr.zero();
512  dg_totalLoadLevel.zero();
513  dg_totalDisp.zero();
514  // loop over dof managers
515  for ( auto &dman : domain->giveDofManagers() ) {
516  if ( !dman->isLocal() ) {
517  continue;
518  }
519 
520  // loop over individual dofs
521  for ( Dof *_idofptr: *dman ) {
522  // loop over dof groups
523  for ( int _dg = 1; _dg <= _ng; _dg++ ) {
524  // test if dof ID is in active set
525  if ( ccDofGroups.at(_dg - 1).find( _idofptr->giveDofID() ) != ccDofGroups.at(_dg - 1).end() ) {
526  int _eq = _idofptr->giveEquationNumber(dn);
527 
528  if ( _eq ) {
529  continue;
530  }
531  dg_forceErr.at(_dg) += rhs.at(_eq) * rhs.at(_eq);
532  dg_dispErr.at(_dg) += ddX.at(_eq) * ddX.at(_eq);
533  // missing - compute norms of total displacement and load vectors (but only for selected dofs)!
534  if ( R0 ) {
535  dg_totalLoadLevel.at(_dg) += R0->at(_eq) * R0->at(_eq);
536  }
537 
538  dg_totalLoadLevel.at(_dg) += R.at(_eq) * R.at(_eq) * Lambda * Lambda;
539  dg_totalDisp.at(_dg) += X.at(_eq) * X.at(_eq);
540  }
541  } // end loop over dof groups
542  } // end loop over DOFs
543  } // end loop over dof managers
544 
545  // loop over elements and their DOFs
546  for ( auto &elem : domain->giveElements() ) {
547  if ( elem->giveParallelMode() != Element_local ) {
548  continue;
549  }
550 
551  // loop over element internal Dofs
552  for ( int _idofman = 1; _idofman <= elem->giveNumberOfInternalDofManagers(); _idofman++ ) {
553  // loop over individual dofs
554  for ( Dof *_idofptr: *elem->giveInternalDofManager(_idofman) ) {
555  // loop over dof groups
556  for ( int _dg = 1; _dg <= _ng; _dg++ ) {
557  // test if dof ID is in active set
558  if ( ccDofGroups.at(_dg - 1).find( _idofptr->giveDofID() ) != ccDofGroups.at(_dg - 1).end() ) {
559  int _eq = _idofptr->giveEquationNumber(dn);
560 
561  if ( _eq ) {
562  continue;
563  }
564  dg_forceErr.at(_dg) += rhs.at(_eq) * rhs.at(_eq);
565  dg_dispErr.at(_dg) += ddX.at(_eq) * ddX.at(_eq);
566  // missing - compute norms of total displacement and load vectors (but only for selected dofs)!
567  if ( R0 ) {
568  dg_totalLoadLevel.at(_dg) += R0->at(_eq) * R0->at(_eq);
569  }
570 
571  dg_totalLoadLevel.at(_dg) += R.at(_eq) * R.at(_eq) * Lambda * Lambda;
572  dg_totalDisp.at(_dg) += X.at(_eq) * X.at(_eq);
573  }
574  } // end loop over dof groups
575  } // end loop over DOFs
576  } // end loop over internal element dofmans
577  } // end loop over elements
578 
579  // exchange individual partition contributions (simultaneously for all groups)
580  FloatArray collectiveErr;
581  parallel_context->accumulate(dg_forceErr, collectiveErr);
582  dg_forceErr = collectiveErr;
583  parallel_context->accumulate(dg_dispErr, collectiveErr);
584  dg_dispErr = collectiveErr;
585  parallel_context->accumulate(dg_totalLoadLevel, collectiveErr);
586  dg_totalLoadLevel = collectiveErr;
587  parallel_context->accumulate(dg_totalDisp, collectiveErr);
588  dg_totalDisp = collectiveErr;
589 
590  OOFEM_LOG_INFO("CALMLS: %-15d %-15e ", nite, Lambda);
591  // loop over dof groups
592  for ( int _dg = 1; _dg <= _ng; _dg++ ) {
593  // compute a relative error norm
594  if ( ( dg_totalLoadLevel.at(_dg) ) < calm_SMALL_ERROR_NUM ) {
595  dg_forceErr.at(_dg) = sqrt( dg_forceErr.at(_dg) );
596  } else {
597  dg_forceErr.at(_dg) = sqrt( dg_forceErr.at(_dg) / dg_totalLoadLevel.at(_dg) );
598  }
599 
600  //
601  // compute displacement error
602  //
603  if ( dg_totalDisp.at(_dg) < calm_SMALL_ERROR_NUM ) {
604  dg_dispErr.at(_dg) = sqrt( dg_dispErr.at(_dg) );
605  } else {
606  dg_dispErr.at(_dg) = sqrt( dg_dispErr.at(_dg) / dg_totalDisp.at(_dg) );
607  }
608 
609  if ( ( fabs( dg_forceErr.at(_dg) ) > rtolf.at(_dg) * CALM_MAX_REL_ERROR_BOUND ) ||
610  ( fabs( dg_dispErr.at(_dg) ) > rtold.at(_dg) * CALM_MAX_REL_ERROR_BOUND ) ) {
611  errorOutOfRange = true;
612  }
613 
614  if ( ( fabs( dg_forceErr.at(_dg) ) > rtolf.at(_dg) ) || ( fabs( dg_dispErr.at(_dg) ) > rtold.at(_dg) ) ) {
615  answer = false;
616  }
617 
618 
619  OOFEM_LOG_INFO( "%-15e %-15e ", dg_forceErr.at(_dg), dg_dispErr.at(_dg) );
620  }
621 
622  OOFEM_LOG_INFO("\n");
623  } else {
624  //
625  // _ng==0 (errors computed for all dofs - this is the default)
626  //
627 
628  //
629  // compute force error(s)
630  //
631  double dXX;
632  forceErr = parallel_context->localNorm(rhs);
633  forceErr *= forceErr;
634  dXX = parallel_context->localNorm(X);
635  dXX *= dXX;
636 
637  double eNorm = internalForcesEBENorm.sum();
638  // we compute a relative error norm
639  if ( ( RR0 + RR * Lambda * Lambda ) > calm_SMALL_ERROR_NUM ) {
640  forceErr = sqrt( forceErr / ( RR0 + RR * Lambda * Lambda ) );
641  } else if ( eNorm > calm_SMALL_ERROR_NUM ) {
642  forceErr = sqrt(forceErr / eNorm);
643  } else {
644  forceErr = sqrt(forceErr);
645  }
646 
647  //
648  // compute displacement error
649  //
650  if ( dXX < calm_SMALL_ERROR_NUM ) {
651  dispErr = drProduct;
652  } else {
653  dispErr = drProduct / dXX;
654  dispErr = sqrt(dispErr);
655  }
656 
657  if ( ( fabs(forceErr) > rtolf.at(1) * CALM_MAX_REL_ERROR_BOUND ) ||
658  ( fabs(dispErr) > rtold.at(1) * CALM_MAX_REL_ERROR_BOUND ) ) {
659  errorOutOfRange = true;
660  }
661 
662  if ( ( fabs(forceErr) > rtolf.at(1) ) || ( fabs(dispErr) > rtold.at(1) ) ) {
663  answer = false;
664  }
665 
666  OOFEM_LOG_INFO("CALMLS: %-15d %-15e %-15e %-15e\n", nite, Lambda, forceErr, dispErr);
667  } // end default case (all dofs conributing)
668 
669  return answer;
670 }
671 
672 
673 
676 {
677  IRResultType result; // Required by IR_GIVE_FIELD macro
678 
679  double oldPsi = Psi; // default from constructor
680  double initialStepLength, forcedInitialStepLength;
681  int hpcMode;
682 
684  if ( Psi < 0. ) {
685  Psi = oldPsi;
686  }
687 
688  nsmax = 30;
690  if ( nsmax < 30 ) {
691  nsmax = 30;
692  }
693 
695 
696  minStepLength = 0.;
698 
700  initialStepLength = maxStepLength;
702 
703  //if (deltaL <= 0.0) deltaL=maxStepLength;
704  // This method (instanciate) is called not only at the beginning but also
705  // after restart from engngModel updateAttributes -> and in this case
706  // we want to keep restored deltaL)
707  if ( ( deltaL <= 0.0 ) || ( deltaL > maxStepLength ) ) {
708  deltaL = initialStepLength;
709  }
710 
711  // using this, one can enforce deltaL from the input file after restart
712  forcedInitialStepLength = 0.;
714  if ( forcedInitialStepLength > 0. ) {
715  deltaL = forcedInitialStepLength;
716  }
717 
720  if ( numberOfRequiredIterations < 3 ) {
722  }
723 
724  if ( numberOfRequiredIterations > 1000 ) {
726  }
727 
729  if ( result == IRRT_OK ) {
730  if ( minIterations > 3 && minIterations < 1000 ) {
732  }
733 
734  if ( nsmax <= minIterations ) {
735  nsmax = minIterations + 1;
736  }
737  }
738 
739  // read if MANRM method is used
740  calm_MANRMSteps = 0;
742  if ( calm_MANRMSteps > 0 ) {
744  } else {
746  }
747 
748  // read if HPC is requested
749  hpcMode = 0;
751 
754 
757  // in calm_HPCIndirectDofMask are stored pairs with following meaning:
758  // inode idof
759  // example HPC 4 1 2 6 1
760  // will yield to HPC for node 4 dof 1 and node 6 dof 1
761  // calm_HPCIndirectDofMask must be converted to indirect map
762  // -> because dof eqs. are not known now, we derefer this to
763  // solveYourselfAt() subroutine. The need for converting is indicated by
764  // calm_HPControl = hpc_init
765  if ( calm_HPCDmanDofSrcArray.giveSize() != 0 ) {
766  int nsize;
767  if ( hpcMode == 1 ) {
769  } else if ( hpcMode == 2 ) {
771  } else {
772  calm_Control = calm_hpc_on; // default is to use hpc_on
773  }
774 
775  if ( ( calm_HPCDmanDofSrcArray.giveSize() % 2 ) != 0 ) {
776  OOFEM_ERROR("HPC Map size must be even number, it contains pairs <node, nodeDof>");
777  }
778 
779  nsize = calm_HPCDmanDofSrcArray.giveSize() / 2;
780  if ( calm_HPCWeights.giveSize() == 0 ) {
781  // no weights -> set to 1.0 by default
782  calm_HPCWeights.resize(nsize);
783  for ( int i = 1; i <= nsize; i++ ) {
784  calm_HPCWeights.at(i) = 1.0;
785  }
786  } else if ( nsize != calm_HPCWeights.giveSize() ) {
787  OOFEM_ERROR("HPC map size and weight array size mismatch");
788  }
789 
790  calm_hpc_init = 1;
791  } else {
792  if ( hpcMode ) {
793  OOFEM_ERROR("HPC Map must be specified");
794  }
795  }
796 
797  int _value = 0;
799  solverType = ( LinSystSolverType ) _value;
800 
801  this->lsFlag = 0; // linesearch default is off
803 
805  if ( ls_tolerance < 0.6 ) {
806  ls_tolerance = 0.6;
807  }
808 
809  if ( ls_tolerance > 0.95 ) {
810  ls_tolerance = 0.95;
811  }
812 
814  if ( amplifFactor < 1.0 ) {
815  amplifFactor = 1.0;
816  }
817 
818  if ( amplifFactor > 10.0 ) {
819  amplifFactor = 10.0;
820  }
821 
823  if ( maxEta < 1.5 ) {
824  maxEta = 1.5;
825  }
826 
827  if ( maxEta > 15.0 ) {
828  maxEta = 15.0;
829  }
830 
831  /* initialize optional dof groups for convergence criteria evaluation */
832  this->nccdg = 0; // default, no dof cc group, all norms evaluated for all dofs
834 
835  if ( nccdg >= 1 ) {
836  IntArray _val;
837  char name [ 12 ];
838  // create an empty set
839  __DofIDSet _set;
840  // resize dof group vector
841  this->ccDofGroups.resize(nccdg, _set);
842  for ( int _i = 0; _i < nccdg; _i++ ) {
843  sprintf(name, "%s%d", _IFT_CylindricalALM_ccdg, _i + 1);
844  // read dof group as int array under ccdg# keyword
845  IR_GIVE_FIELD(ir, _val, name);
846  // convert aray into set
847  for ( int _j = 1; _j <= _val.giveSize(); _j++ ) {
848  ccDofGroups.at(_i).insert( ( DofIDItem ) _val.at(_j) );
849  }
850  }
851 
852  // read relative error tolerances of the solver fo each cc
853  // if common rtolv provided, set to this tolerace both rtolf and rtold
855  rtold = rtolf;
856  // read optional force and displacement tolerances
859 
860  if ( ( rtolf.giveSize() != nccdg ) || ( rtold.giveSize() != nccdg ) ) {
861  OOFEM_ERROR("Incompatible size of rtolf or rtold params, expected size %d (nccdg)", nccdg);
862  }
863  } else {
864  nccdg = 0;
865  double _rtol = 1.e-3; // default tolerance
866  rtolf.resize(1);
867  rtold.resize(1);
868  // read relative error tolerances of the solver
869  // if common rtolv provided, set to this tolerace both rtolf and rtold
871  rtolf.at(1) = rtold.at(1) = _rtol;
873  rtolf.at(1) = _rtol;
875  rtold.at(1) = _rtol;
876  }
877 
878  this->giveLinearSolver()->initializeFrom(ir);
879 
881 
882  return IRRT_OK;
883 }
884 
885 
887 //
888 // converts HPC map from user input map to HPC indirect Map
889 //
890 // indirect map:
891 // size of indirect map is number of controlled DOFs
892 // on i-th position this map contain equation number of i-th controlled dof
893 //
894 // user input map;
895 // user input map has size 2*controlled DOFs
896 // and contain pairs (node, nodeDof);
897 //
898 // This is used in order to hide equation numbering from user
899 //
900 {
901  IntArray indirectMap;
902  FloatArray weights;
903  int size;
905 
906  int count = 0;
907  size = calm_HPCDmanDofSrcArray.giveSize() / 2;
908  indirectMap.resize(size);
909  weights.resize(size);
910  for ( auto &dman : domain->giveDofManagers() ) {
911  int jglobnum = dman->giveLabel();
912  for ( int i = 1; i <= size; i++ ) {
913  int inode = calm_HPCDmanDofSrcArray.at(2 * i - 1);
914  int idofid = calm_HPCDmanDofSrcArray.at(2 * i);
915  if ( inode == jglobnum ) {
916  if ( parallel_context->isLocal( dman.get() ) ) {
917  indirectMap.at(++count) = dman->giveDofWithID(idofid)->giveEquationNumber(dn);
918  if ( calm_Control == calml_hpc ) {
919  weights.at(count) = calm_HPCDmanWeightSrcArray.at(i);
920  }
921  }
922 
923  continue;
924  }
925  }
926  }
927 
928  if ( count != size ) {
929  OOFEM_WARNING("some dofmans/Dofs in HPCarray not recognized");
930  }
931 
933  if ( calm_Control == calml_hpc ) {
934  calm_HPCWeights.resize(count);
935  }
936 
937  for ( int i = 1; i <= count; i++ ) {
938  calm_HPCIndirectDofMask.at(i) = indirectMap.at(i);
939  calm_HPCWeights.at(i) = weights.at(i);
940  }
941 }
942 
943 
946 {
947  // write current deltaL
948  if ( !stream.write(deltaL) ) {
950  }
951 
952  return CIO_OK;
953 }
954 
955 
958 {
959  // read last deltaL
960  if ( !stream.read(deltaL) ) {
962  }
963 
964  return CIO_OK;
965 }
966 
967 
970 {
971  if ( linSolver ) {
972  if ( linSolver->giveLinSystSolverType() == solverType ) {
973  return linSolver.get();
974  }
975  }
976 
978  if ( !linSolver ) {
979  OOFEM_ERROR("linear solver creation failed for lstype %d", solverType);
980  }
981 
982  return linSolver.get();
983 }
984 
985 
986 int
987 CylindricalALM :: computeDeltaLambda(double &deltaLambda, const FloatArray &dX, const FloatArray &deltaXt,
988  const FloatArray &deltaX_, const FloatArray &R, double RR, double eta,
989  double deltaL, double DeltaLambda0, int neq)
990 {
991  double a1 = 0.0, a2 = 0.0, a3 = 0.0, a4, a5;
992  //
993  // B.3.
994  //
995  if ( ( calm_Control == calm_hpc_off ) || ( calm_Control == calm_hpc_on ) ) {
996  if ( calm_Control == calm_hpc_off ) {
997  // this two lines are necessary if NRM is used
998  // (for MNRM they can be computed at startup A1).
999  double XX = parallel_context->localNorm(deltaXt);
1000  XX *= XX;
1001  double XXt = parallel_context->localDotProduct(dX, deltaXt);
1002  double X_Xt = parallel_context->localDotProduct(deltaX_, deltaXt);
1003  double dXdX = parallel_context->localNorm(dX);
1004  dXdX *= dXdX;
1005  double dXX_ = parallel_context->localDotProduct(dX, deltaX_);
1006  double X_X_ = parallel_context->localNorm(deltaX_);
1007  X_X_ *= X_X_;
1008 
1009  a1 = eta * eta * XX + Psi * Psi * RR;
1010  a2 = RR * Psi * Psi * DeltaLambda0 * 2.0
1011  + 2.0 * eta * XXt
1012  + 2.0 * eta * eta * X_Xt;
1013  a3 = dXdX
1014  + 2.0 * eta * dXX_
1015  + eta * eta * X_X_
1016  + DeltaLambda0 * DeltaLambda0 * RR * Psi * Psi - deltaL * deltaL;
1017  } else if ( calm_Control == calm_hpc_on ) {
1018  double _rr = 0.;
1019  double _RR = 0.;
1020  double _a2 = 0.;
1021  double _a3 = 0.;
1022  for ( int i = 1; i <= calm_HPCIndirectDofMask.giveSize(); i++ ) {
1023  int ind;
1024  if ( ( ind = calm_HPCIndirectDofMask.at(i) ) != 0 ) {
1025  double _pr = ( dX.at(ind) + eta * deltaX_.at(ind) );
1026  _rr += deltaXt.at(ind) * deltaXt.at(ind);
1027  _RR += R.at(ind) * R.at(ind);
1028  _a2 += eta * deltaXt.at(ind) * _pr;
1029  _a3 += _pr * _pr;
1030  }
1031  }
1032 
1033  FloatArray col_;
1034  parallel_context->accumulate({_rr, _RR, _a2, _a3}, col_);
1035  a1 = eta * eta * col_(0) + Psi *Psi *col_(1);
1036  a2 = col_(1) * Psi * Psi * DeltaLambda0 * 2.0;
1037  a2 += 2.0 * col_(2);
1038  a3 = col_(3) - deltaL * deltaL + DeltaLambda0 *DeltaLambda0 *col_(1) * Psi * Psi;
1039  //printf ("\na1=%e, a2=%e, a3=%e", a1,a2,a3);
1040  }
1041 
1042  // solution of quadratic eqn.
1043  double discr = a2 * a2 - 4.0 * a1 * a3;
1044  if ( discr < 0.0 ) {
1045  OOFEM_ERROR("discriminant is negative, solution failed");
1046  }
1047 
1048  discr = sqrt(discr);
1049  double lam1 = ( -a2 + discr ) / 2. / a1;
1050  double lam2 = ( -a2 - discr ) / 2. / a1;
1051 
1052  // select better lam (according to angle between deltar0 and deltar1(2).
1053  //
1054  // up to there rewritten
1055  //
1056  if ( calm_Control == calm_hpc_off ) {
1057  double tmp = parallel_context->localNorm(dX);
1058  tmp *= tmp;
1059  a4 = eta * parallel_context->localDotProduct(dX, deltaX_) + tmp;
1060  a5 = eta * parallel_context->localDotProduct(dX, deltaXt);
1061  } else {
1062  a4 = 0.;
1063  a5 = 0.;
1064  for ( int i = 1; i <= calm_HPCIndirectDofMask.giveSize(); i++ ) {
1065  int ind;
1066  if ( ( ind = calm_HPCIndirectDofMask.at(i) ) != 0 ) {
1067  a4 += eta * dX.at(ind) * deltaX_.at(ind) + dX.at(ind) * dX.at(ind);
1068  a5 += eta * dX.at(ind) * deltaXt.at(ind);
1069  }
1070  }
1071 
1072  // In case of parallel simulations (equiv to no-op on seq sim):
1073  FloatArray cola;
1074  parallel_context->accumulate({a4, a5}, cola);
1075  a4 = cola(0);
1076  a5 = cola(1);
1077  }
1078 
1079  double cos1 = ( a4 + a5 * lam1 ) / deltaL / deltaL;
1080  double cos2 = ( a4 + a5 * lam2 ) / deltaL / deltaL;
1081  if ( cos1 > cos2 ) {
1082  deltaLambda = lam1;
1083  } else {
1084  deltaLambda = lam2;
1085  }
1086 
1087  //printf ("eta=%e, lam1=%e, lam2=%e", eta, lam1, lam2);
1088  } else if ( calm_Control == calml_hpc ) {
1089  // linearized control
1090  double nom = 0., denom = 0.;
1091 
1092  for ( int i = 1; i <= calm_HPCIndirectDofMask.giveSize(); i++ ) {
1093  int ind;
1094  if ( ( ind = calm_HPCIndirectDofMask.at(i) ) != 0 ) {
1095  nom += ( dX.at(ind) + eta * deltaX_.at(ind) ) * calm_HPCWeights.at(i);
1096  denom += eta * deltaXt.at(ind) * calm_HPCWeights.at(i);
1097  }
1098  }
1099 
1100  // In case of parallel simulations (equiv to no-op on seq sim):
1101  FloatArray colv;
1102  parallel_context->accumulate({nom, denom}, colv);
1103  nom = colv(0);
1104  denom = colv(1);
1105 
1106  if ( fabs(denom) < calm_SMALL_NUM ) {
1107  OOFEM_ERROR("zero denominator in linearized control");
1108  }
1109 
1110  deltaLambda = ( deltaL - nom ) / denom;
1111  }
1112 
1113  return 0;
1114 }
1115 
1116 
1117 void
1118 CylindricalALM :: search(int istep, FloatArray &prod, FloatArray &eta, double amp,
1119  double maxetalim, double minetalim, int &ico)
1120 {
1121  int ineg = 0;
1122  double etaneg = 1.0;
1123  double etamax = 0.0;
1124 
1125 
1126  // obtain ineg (number of previous line search iteration with negative ratio nearest to origin)
1127  // as well as max previous step length, etamax
1128 
1129  for ( int i = 1; i <= istep; i++ ) {
1130  etamax = max( etamax, eta.at(i) );
1131  if ( prod.at(i) >= 0.0 ) {
1132  continue;
1133  }
1134 
1135  if ( eta.at(i) >= etaneg ) {
1136  continue;
1137  }
1138 
1139  etaneg = eta.at(i);
1140  ineg = i;
1141  }
1142 
1143  if ( ineg ) {
1144  // allow interpolation
1145  // first find ipos (position of previous s-l with positive ratio that is
1146  // closest to ineg (but with smaller s-l)
1147  int ipos = 1;
1148  for ( int i = 1; i <= istep; i++ ) {
1149  if ( prod.at(i) <= 0.0 ) {
1150  continue;
1151  }
1152 
1153  if ( eta.at(i) > eta.at(ineg) ) {
1154  continue;
1155  }
1156 
1157  if ( eta.at(i) < eta.at(ipos) ) {
1158  continue;
1159  }
1160 
1161  ipos = i;
1162  }
1163 
1164  // interpolate to get step-length
1165  double etaint = ( prod.at(ineg) * eta.at(ipos) - prod.at(ipos) * eta.at(ineg) ) / ( prod.at(ineg) - prod.at(ipos) );
1166  // alternatively get eta ensuring reasonable change
1167  double etaalt = eta.at(ipos) + 0.2 * ( eta.at(ineg) - eta.at(ipos) );
1168  etaint = max(etaint, etaalt);
1169  if ( etaint < minetalim ) {
1170  etaint = minetalim;
1171  if ( ico == 1 ) {
1172  ico = 2;
1173  } else {
1174  ico = 1;
1175  }
1176  }
1177 
1178  eta.at(istep + 1) = etaint;
1179  } else { // ineq == 0
1180  // allow extrapolation
1181  double etamaxstep = amp * etamax;
1182  // extrapolate between current and previous
1183  double etaextrap = ( prod.at(istep) * eta.at(istep - 1) - prod.at(istep - 1) * eta.at(istep) ) /
1184  ( prod.at(istep) - prod.at(istep - 1) );
1185  eta.at(istep + 1) = etaextrap;
1186  // check if in limits
1187  if ( ( etaextrap <= 0.0 ) || ( etaextrap > etamaxstep ) ) {
1188  eta.at(istep + 1) = etamaxstep;
1189  }
1190 
1191  if ( ( eta.at(istep + 1) > maxetalim ) && ( ico == 1 ) ) {
1192  ico = 2;
1193  return;
1194  }
1195 
1196  if ( ( eta.at(istep + 1) > maxetalim ) ) {
1197  ico = 1;
1198  eta.at(istep + 1) = maxetalim;
1199  }
1200  }
1201 }
1202 
1203 void
1204 CylindricalALM :: do_lineSearch(FloatArray &r, const FloatArray &rInitial, const FloatArray &deltaX_, const FloatArray &deltaXt,
1205  const FloatArray &dXm1, FloatArray &dX, FloatArray &ddX,
1206  const FloatArray &R, const FloatArray *R0, const FloatArray &F,
1207  double &DeltaLambda, double &DeltaLambdam1, double &deltaLambda,
1208  double &Lambda, double &ReachedLambda, double RR, double &drProduct, TimeStep *tStep)
1209 {
1210  //
1211  // LINE SEARCH
1212  //
1213 
1214  int neq = r.giveSize();
1215  int ls_failed, dl_failed = 0;
1216  int _iter = 0;
1217  int ico;
1218  int ls_maxiter = 10;
1219 
1220  DeltaLambda = DeltaLambdam1 + deltaLambda;
1221  Lambda = ReachedLambda + DeltaLambda;
1222  double deltaLambdaForEta1 = deltaLambda;
1223 
1224  double d6, d7, d8, d9;
1225 
1226  d6 = parallel_context->localDotProduct(deltaX_, F);
1227  d7 = parallel_context->localDotProduct(deltaXt, F);
1228  d8 = -1.0 * parallel_context->localDotProduct(deltaX_, R);
1229  d9 = -1.0 * parallel_context->localDotProduct(deltaXt, R);
1230 
1231  double e1, e2, d10 = 0.0, d11 = 0.0;
1232  double s0, si;
1233  double prevEta, currEta;
1234 
1235  FloatArray eta(ls_maxiter + 1), prod(ls_maxiter + 1);
1236 
1237 
1238  if ( R0 ) {
1239  d10 = -1.0 * parallel_context->localDotProduct(deltaX_, * R0);
1240  d11 = -1.0 * parallel_context->localDotProduct(deltaXt, * R0);
1241  }
1242 
1243  // prepare starting product ratios and step lengths
1244  prod.at(1) = 1.0;
1245  eta.at(1) = 0.0;
1246  currEta = eta.at(2) = 1.0;
1247  // following counter shows how many times the max or min step length has been reached
1248  ico = 0;
1249 
1250  //
1251  // begin line search loop
1252  //
1253  ls_failed = 1;
1254  for ( int ils = 2; ils <= ls_maxiter; ils++ ) {
1255  // update displacements
1256  drProduct = 0.0; // dotproduct of iterative displacement increment vector
1257 
1258  ddX.clear();
1259  ddX.add(eta.at(ils) * deltaLambda, deltaXt);
1260  ddX.add(eta.at(ils), deltaX_);
1261  dX = dXm1;
1262  dX.add(ddX);
1263 
1264  drProduct = parallel_context->localNorm(ddX);
1265  drProduct *= drProduct;
1266 
1267  tStep->incrementStateCounter(); // update solution state counter
1268  // update internal forces according to new state
1270 
1271  e1 = parallel_context->localDotProduct(deltaX_, F);
1272  e2 = parallel_context->localDotProduct(deltaXt, F);
1273 
1274  s0 = d6 + deltaLambda * d7 + Lambda * d8 + deltaLambda * Lambda * d9 + d10 + deltaLambda * d11;
1275  si = e1 + deltaLambda * e2 + Lambda * d8 + deltaLambda * Lambda * d9 + d10 + deltaLambda * d11;
1276  prod.at(ils) = si / s0;
1277 
1278  //printf ("\ns0=%e, si=%e, prod=%e", s0, si, prod.at(ils));
1279  if ( s0 >= 0.0 ) {
1280  //printf ("solve starting inner product uphill, val=%e",s0);
1281  ls_failed = 3;
1282  currEta = 1.0;
1283  break;
1284  }
1285 
1286  if ( fabs(si / s0) < ls_tolerance ) {
1287  ls_failed = 0;
1288  currEta = eta.at(ils);
1289  break;
1290  }
1291 
1292  _iter = 0;
1293 
1294  currEta = eta.at(ils);
1295  //printf ("\n_ite=%d, deltaLambda=%e, eta=%e", _iter, deltaLambda, currEta);
1296  do { // solve simultaneously the equations for eta and lambda
1297  _iter++;
1298  prevEta = currEta;
1299  s0 = d6 + deltaLambda * d7 + Lambda * d8 + deltaLambda * Lambda * d9 + d10 + deltaLambda * d11;
1300  si = e1 + deltaLambda * e2 + Lambda * d8 + deltaLambda * Lambda * d9 + d10 + deltaLambda * d11;
1301  prod.at(ils) = si / s0;
1302 
1303  // call line-search routine to get new estimate of eta.at(ils+1)
1304  this->search(ils, prod, eta, amplifFactor, maxEta, minEta, ico);
1305  if ( ico == 2 ) {
1306  ls_failed = 2;
1307  break; // exit the loop
1308  }
1309 
1310  currEta = eta.at(ils + 1);
1311  // solve for deltaLambda
1312  dl_failed = this->computeDeltaLambda(deltaLambda, dXm1, deltaXt, deltaX_, R, RR, currEta, deltaL, DeltaLambdam1, neq);
1313  if ( dl_failed ) {
1314  eta.at(ils + 1) = 1.0;
1315  deltaLambda = deltaLambdaForEta1;
1316  break;
1317  }
1318 
1319  DeltaLambda = DeltaLambdam1 + deltaLambda;
1320  Lambda = ReachedLambda + DeltaLambda;
1321  //printf ("\n_ite=%d, deltaLambda=%e, eta=%e", _iter, deltaLambda, currEta);
1322  } while ( ( _iter < 10 ) && ( fabs( ( currEta - prevEta ) / prevEta ) > 0.01 ) );
1323 
1324  if ( ( ls_failed > 1 ) || dl_failed ) {
1325  break;
1326  }
1327 
1328  //printf ("\ncalm ls...");
1329  //printf ("eta = %e, err=%d, ", currEta,ls_failed);
1330  //printf ("dLambda=%e, lerr=%d ", deltaLambda, dl_failed);
1331  } // end of line search loop
1332 
1333  if ( ls_failed || dl_failed ) {
1334  // last resort
1335  deltaLambda = deltaLambdaForEta1;
1336  drProduct = 0.0; // dotproduct of iterative displacement increment vector
1337 
1338  ddX.clear();
1339  ddX.add(deltaLambda, deltaXt);
1340  ddX.add(deltaX_);
1341  dX = dXm1;
1342  dX.add(ddX);
1343 
1344  drProduct = parallel_context->localNorm(ddX);
1345  drProduct *= drProduct;
1346 
1347  tStep->incrementStateCounter(); // update solution state counter
1349  DeltaLambda = DeltaLambdam1 + deltaLambda;
1350  Lambda = ReachedLambda + DeltaLambda;
1351 
1352  OOFEM_LOG_INFO("CALMLS: Line search - err_id=%d, eta=%e, dlambda=%e\n", ls_failed, 1.0, deltaLambda);
1353  } else {
1354  OOFEM_LOG_INFO("CALMLS: Line search - err_id=%d, eta=%e, dlambda=%e\n", ls_failed, currEta, deltaLambda);
1355  }
1356 }
1357 } // end namespace oofem
virtual ~CylindricalALM()
Definition: calmls.C:103
LinSystSolverType
The values of this type should be related not to specific solvers, but more to specific packages that...
The representation of EngngModel default unknown numbering.
void subtract(const FloatArray &src)
Subtracts array src to receiver.
Definition: floatarray.C:258
#define NM_Success
Numerical method exited with success.
Definition: nmstatus.h:47
#define _IFT_CylindricalALM_minsteplength
Definition: calmls.h:54
int nccdg
Number of convergence criteria dof groups.
Definition: calmls.h:202
Class and object Domain.
Definition: domain.h:115
virtual void applyPerturbation(FloatArray *displacement)
bool isLocal(DofManager *dman)
virtual IRResultType initializeFrom(InputRecord *ir)
Definition: nummet.h:101
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
#define _IFT_CylindricalALM_reqiterations
Definition: calmls.h:58
virtual NM_Status solve(SparseMtrx &K, FloatArray &R, FloatArray *R0, FloatArray &X, FloatArray &dX, FloatArray &F, const FloatArray &internalForcesEBENorm, double &ReachedLambda, referenceLoadInputModeType rlm, int &nite, TimeStep *)
Solves the given sparse linear system of equations .
Definition: calmls.C:109
#define _IFT_CylindricalALM_initialsteplength
Definition: calmls.h:56
The purpose of DataStream abstract class is to allow to store/restore context to different streams...
Definition: datastream.h:54
ExportModuleManager * giveExportModuleManager()
Returns receiver&#39;s export module manager.
Definition: engngm.h:758
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
#define _IFT_CylindricalALM_nccdg
Definition: calmls.h:69
int max(int i, int j)
Returns bigger value form two given decimals.
Definition: mathfem.h:71
int computeDeltaLambda(double &deltaLambda, const FloatArray &dX, const FloatArray &deltaXt, const FloatArray &deltaX_, const FloatArray &R, double RR, double eta, double deltaL, double DeltaLambda0, int neq)
Definition: calmls.C:987
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1) ...
Definition: mathfem.h:91
FloatArray rtolf
Relative unbalanced force tolerance for each group.
Definition: calmls.h:206
This base class is an abstraction for all numerical methods solving sparse linear system of equations...
void clear()
Clears receiver (zero size).
Definition: floatarray.h:206
#define _IFT_CylindricalALM_psi
Definition: calmls.h:51
REGISTER_SparseNonLinearSystemNM(CylindricalALM)
Definition: calmls.C:58
#define _IFT_CylindricalALM_hpc
Definition: calmls.h:62
double minStepLength
Definition: calmls.h:166
#define _IFT_CylindricalALM_hpcmode
Definition: calmls.h:61
virtual SparseLinearSystemNM * giveLinearSolver()
Constructs (if necessary) and returns a linear solver.
Definition: calmls.C:969
Linearized ALM (only displacements), taking into account only selected dofs with given weight...
Definition: calmls.h:151
void incrementStateCounter()
Updates solution state counter.
Definition: timestep.h:190
void doOutput(TimeStep *tStep, bool substepFlag=false)
Writes the output.
#define _IFT_CylindricalALM_ccdg
Definition: calmls.h:70
void search(int istep, FloatArray &prod, FloatArray &eta, double amp, double maxeta, double mineta, int &status)
Definition: calmls.C:1118
std::vector< std::unique_ptr< DofManager > > & giveDofManagers()
Definition: domain.h:400
General IO error.
Full ALM with quadratic constrain and all dofs.
Definition: calmls.h:149
FloatArray calm_HPCWeights
Definition: calmls.h:178
unsigned long NM_Status
Mask defining NumMetod Status; which can be asked after finishing computation by Numerical Method...
Definition: nmstatus.h:44
Class implementing an array of integers.
Definition: intarray.h:61
int & at(int i)
Coefficient access function.
Definition: intarray.h:103
virtual int read(int *data, int count)=0
Reads count integer values into array pointed by data.
#define calm_SMALL_ERROR_NUM
Definition: calmls.h:83
#define THROW_CIOERR(e)
Definition: contextioerr.h:61
calm_ControlType calm_Control
Definition: calmls.h:177
#define CALM_DEFAULT_NRM_TICKS
Definition: calmls.C:55
int lsFlag
Line search flag.
Definition: calmls.h:192
virtual void initStepIncrements()
Initializes solution of new time step.
Definition: engngm.C:1496
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
#define _IFT_CylindricalALM_maxrestarts
Definition: calmls.h:53
void convertHPCMap()
Definition: calmls.C:886
Domain * domain
Pointer to domain.
Definition: nummet.h:84
virtual int write(const int *data, int count)=0
Writes count integer values from array pointed by data.
double sum() const
Computes the sum of receiver values.
Definition: floatarray.C:852
double amplifFactor
Line search amplification factor.
Definition: calmls.h:196
double localDotProduct(const FloatArray &a, const FloatArray &b)
Dot product for a locally distributed array.
#define _IFT_CylindricalALM_maxiter
Definition: calmls.h:52
#define _IFT_CylindricalALM_rtold
Definition: calmls.h:73
int giveNumber()
Returns receiver&#39;s number.
Definition: timestep.h:129
#define OOFEM_LOG_INFO(...)
Definition: logger.h:127
Keeps the old tangent.
Definition: calmls.h:156
bool checkConvergence(const FloatArray &R, const FloatArray *R0, const FloatArray &F, const FloatArray &X, const FloatArray &ddX, double Lambda, double RR0, double RR, double drProduct, const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange)
Evaluates the convergence criteria.
Definition: calmls.C:478
virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj=NULL)
Definition: calmls.C:945
#define _IFT_CylindricalALM_forcedinitialsteplength
Definition: calmls.h:57
std::vector< __DofIDSet > ccDofGroups
Convergence criteria dof groups.
Definition: calmls.h:204
#define _IFT_CylindricalALM_rtolv
Definition: calmls.h:71
#define OOFEM_ERROR(...)
Definition: error.h:61
void clear()
Clears the array (zero size).
Definition: intarray.h:177
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
double maxStepLength
Definition: calmls.h:166
#define _IFT_CylindricalALM_lsearchmaxeta
Definition: calmls.h:68
Implementation of sparse nonlinear solver with indirect control.
Definition: calmls.h:144
FloatArray rtold
Relative iterative displacement change tolerance for each group.
Definition: calmls.h:208
calm_NR_ModeType calm_NR_OldMode
Definition: calmls.h:168
#define CALM_RESET_STEP_REDUCE
Definition: calmls.C:53
referenceLoadInputModeType
The following parameter allows to specify how the reference load vector is obtained from given totalL...
std::unique_ptr< SparseLinearSystemNM > linSolver
Linear system solver.
Definition: calmls.h:187
void resize(int n)
Checks size of receiver towards requested bounds.
Definition: intarray.C:124
#define _IFT_CylindricalALM_miniterations
Definition: calmls.h:59
FloatArray calm_HPCDmanWeightSrcArray
Input array of dofman weights (for hpcmode 2).
Definition: calmls.h:184
int numberOfRequiredIterations
Definition: calmls.h:167
int minIterations
Minimum hard number of iteration.s.
Definition: calmls.h:173
#define NM_None
Definition: nmstatus.h:46
double maxEta
Line search parameters (limits).
Definition: calmls.h:198
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
Full ALM with quadratic constrain, taking into account only selected dofs.
Definition: calmls.h:150
calm_NR_ModeType calm_NR_Mode
Definition: calmls.h:168
IRResultType initializeFrom(InputRecord *ir)
Element is local, there are no contributions from other domains to this element.
Definition: element.h:101
#define _IFT_CylindricalALM_lstype
Definition: calmls.h:64
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
#define _IFT_CylindricalALM_linesearch
Definition: calmls.h:65
#define _IFT_CylindricalALM_lsearchamp
Definition: calmls.h:67
Class representing the general Input Record.
Definition: inputrecord.h:101
ParallelContext * parallel_context
Parallel context for computing norms, dot products and such.
Definition: calmls.h:210
#define calm_SMALL_NUM
Definition: calmls.h:82
IntArray calm_HPCIndirectDofMask
Array containing equation numbers of dofs under indirect control.
Definition: calmls.h:180
#define CALM_MAX_REL_ERROR_BOUND
Definition: calmls.C:56
void zero()
Zeroes all coefficients of receiver.
Definition: floatarray.C:658
void do_lineSearch(FloatArray &X, const FloatArray &XInitial, const FloatArray &deltaX_, const FloatArray &deltaXt, const FloatArray &dXm1, FloatArray &dX, FloatArray &ddX, const FloatArray &R, const FloatArray *R0, const FloatArray &F, double &DeltaLambda, double &DeltaLambdam1, double &deltaLambda, double &Lambda, double &ReachedLambda, double RR, double &drProduct, TimeStep *tStep)
Perform line search optimization of step length.
Definition: calmls.C:1204
void times(double s)
Multiplies receiver with scalar.
Definition: floatarray.C:818
#define _IFT_CylindricalALM_rtolf
Definition: calmls.h:72
Updates the tangent every iteration.
Definition: calmls.h:157
double accumulate(double local)
Accumulates the global value.
ClassFactory & classFactory
Definition: classfactory.C:59
long ContextMode
Context mode (mask), defining the type of information written/read to/from context.
Definition: contextmode.h:43
IntArray calm_HPCDmanDofSrcArray
Input array containing dofmanagers and corresponding dof numbers under indirect control.
Definition: calmls.h:182
double ls_tolerance
Line search tolerance.
Definition: calmls.h:194
std::vector< std::unique_ptr< Element > > & giveElements()
Definition: domain.h:279
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj=NULL)
Definition: calmls.C:957
int giveSize() const
Definition: intarray.h:203
Updates the tangent after a few steps.
Definition: calmls.h:158
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.
#define _IFT_CylindricalALM_lsearchtol
Definition: calmls.h:66
#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_CylindricalALM_hpcw
Definition: calmls.h:63
virtual IRResultType initializeFrom(InputRecord *ir)
Definition: calmls.C:675
EngngModel * engngModel
Pointer to engineering model.
Definition: nummet.h:86
double localNorm(const FloatArray &src)
Norm for a locally distributed array.
#define OOFEM_WARNING(...)
Definition: error.h:62
int calm_hpc_init
Variables for HyperPlaneControl.
Definition: calmls.h:176
Class representing solution step.
Definition: timestep.h:80
LinSystSolverType solverType
linear system solver ID.
Definition: calmls.h:189
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
#define _IFT_CylindricalALM_manrmsteps
Definition: calmls.h:60
std::set< DofIDItem > __DofIDSet
Definition: calmls.h:161
#define _IFT_CylindricalALM_steplength
Definition: calmls.h:55
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:27 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011