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

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011