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
61 SparseNonLinearSystemNM(d, m), calm_HPCWeights(), calm_HPCIndirectDofMask(), calm_HPCDmanDofSrcArray(), ccDofGroups(), old_dX()
64 numberOfRequiredIterations = 3;
69 calm_NR_Mode = calm_NR_OldMode = calm_modifiedNRM;
70 calm_NR_ModeTick = -1;
80 calm_Control = calm_hpc_off;
99 parallel_context = engngModel->giveParallelContext( d->
giveNumber() );
103CylindricalALM :: ~CylindricalALM()
113 FloatArray rhs, deltaXt, deltaX_, dXm1, XInitial;
116 double XX, RR, RR0, XR, p = 0.0;
117 double deltaLambda, Lambda, eta, DeltaLambdam1, DeltaLambda = 0.0;
118 double drProduct = 0.0;
124 bool converged, errorOutOfRangeFlag;
129 OOFEM_LOG_INFO(
"CALMLS: Iteration LoadLevel ForceError DisplError \n");
130 OOFEM_LOG_INFO(
"----------------------------------------------------------------------------\n");
133 for ( i = 1; i <=
nccdg; i++ ) {
137 OOFEM_LOG_INFO(
"\n__________________________________________________________\n");
201 SparseNonLinearSystemNM :: applyPerturbation(& deltaXt);
206 p = sqrt(XX +
Psi *
Psi * RR);
211 for ( i = 1; i <= HPsize; i++ ) {
213 _XX += deltaXt.
at(ind) * deltaXt.
at(ind);
214 _RR += R.
at(ind) * R.
at(ind);
221 _XX = collected_XXRR(0);
222 _RR = collected_XXRR(1);
224 p = sqrt(_XX +
Psi *
Psi * _RR);
228 for ( i = 1; i <= HPsize; i++ ) {
238 Lambda = ReachedLambda;
250 DeltaLambda = deltaLambda =
sgn(XR) *
deltaL / p;
251 Lambda += DeltaLambda;
257 rhs.
times(DeltaLambda);
275 DeltaLambdam1 = DeltaLambda;
349 if ( this->
lsFlag && ( nite != 1 ) ) {
356 DeltaLambda, DeltaLambdam1, deltaLambda, Lambda, ReachedLambda,
357 RR, drProduct, tStep);
363 ddX.
add(eta * deltaLambda, deltaXt);
364 ddX.
add(eta, deltaX_);
371 drProduct *= drProduct;
377 DeltaLambda = DeltaLambdam1 + deltaLambda;
378 Lambda = ReachedLambda + DeltaLambda;
390 converged = this->
checkConvergence(R, R0, F, X, ddX, Lambda, RR0, RR, drProduct,
391 internalForcesEBENorm, nite, errorOutOfRangeFlag);
392 if ( ( nite >=
nsmax ) || errorOutOfRangeFlag ) {
427 engngModel->giveExportModuleManager()->doOutput(tStep,
true);
442 bk = DeltaLambda * RDR / ( DR * DR );
478 ReachedLambda = Lambda;
486 double Lambda,
double RR0,
double RR,
double drProduct,
487 const FloatArray &internalForcesEBENorm,
int nite,
bool &errorOutOfRange)
495 double forceErr, dispErr;
502 errorOutOfRange =
false;
514 forceErr = dispErr = 0.0;
518 dg_totalLoadLevel.zero();
521 for (
auto &dman :
domain->giveDofManagers() ) {
522 if ( !dman->isLocal() ) {
527 for (
Dof *_idofptr : *dman ) {
529 for (
int _dg = 1; _dg <= _ng; _dg++ ) {
532 int _eq = _idofptr->giveEquationNumber(dn);
537 dg_forceErr.at(_dg) += rhs.
at(_eq) * rhs.
at(_eq);
538 dg_dispErr.at(_dg) += ddX.
at(_eq) * ddX.
at(_eq);
541 dg_totalLoadLevel.at(_dg) += R0->
at(_eq) * R0->
at(_eq);
544 dg_totalLoadLevel.at(_dg) += R.
at(_eq) * R.
at(_eq) * Lambda * Lambda;
545 dg_totalDisp.
at(_dg) += X.
at(_eq) * X.
at(_eq);
552 for (
auto &elem :
domain->giveElements() ) {
558 for (
int _idofman = 1; _idofman <= elem->giveNumberOfInternalDofManagers(); _idofman++ ) {
560 for (
Dof *_idofptr : *elem->giveInternalDofManager(_idofman) ) {
562 for (
int _dg = 1; _dg <= _ng; _dg++ ) {
565 int _eq = _idofptr->giveEquationNumber(dn);
570 dg_forceErr.at(_dg) += rhs.
at(_eq) * rhs.
at(_eq);
571 dg_dispErr.at(_dg) += ddX.
at(_eq) * ddX.
at(_eq);
574 dg_totalLoadLevel.at(_dg) += R0->
at(_eq) * R0->
at(_eq);
577 dg_totalLoadLevel.at(_dg) += R.
at(_eq) * R.
at(_eq) * Lambda * Lambda;
578 dg_totalDisp.
at(_dg) += X.
at(_eq) * X.
at(_eq);
588 dg_forceErr = collectiveErr;
590 dg_dispErr = collectiveErr;
592 dg_totalLoadLevel = collectiveErr;
594 dg_totalDisp = collectiveErr;
598 for (
int _dg = 1; _dg <= _ng; _dg++ ) {
601 dg_forceErr.at(_dg) = sqrt( dg_forceErr.at(_dg) );
603 dg_forceErr.at(_dg) = sqrt( dg_forceErr.at(_dg) / dg_totalLoadLevel.at(_dg) );
610 dg_dispErr.at(_dg) = sqrt( dg_dispErr.at(_dg) );
612 dg_dispErr.at(_dg) = sqrt( dg_dispErr.at(_dg) / dg_totalDisp.
at(_dg) );
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;
620 if ( ( fabs( dg_forceErr.at(_dg) ) >
rtolf.at(_dg) ) || ( fabs( dg_dispErr.at(_dg) ) >
rtold.at(_dg) ) ) {
625 OOFEM_LOG_INFO(
"%-15e %-15e ", dg_forceErr.at(_dg), dg_dispErr.at(_dg) );
639 forceErr *= forceErr;
643 double eNorm = internalForcesEBENorm.
sum();
646 forceErr = sqrt( forceErr / ( RR0 + RR * Lambda * Lambda ) );
648 forceErr = sqrt(forceErr / eNorm);
650 forceErr = sqrt(forceErr);
659 dispErr = drProduct / dXX;
660 dispErr = sqrt(dispErr);
665 errorOutOfRange =
true;
668 if ( ( fabs(forceErr) >
rtolf.at(1) ) || ( fabs(dispErr) >
rtold.at(1) ) ) {
672 OOFEM_LOG_INFO(
"CALMLS: %-15d %-15e %-15e %-15e\n", nite, Lambda, forceErr, dispErr);
683 SparseNonLinearSystemNM :: initializeFrom(ir);
686 double initialStepLength, forcedInitialStepLength;
714 deltaL = initialStepLength;
718 forcedInitialStepLength = 0.;
720 if ( forcedInitialStepLength > 0. ) {
721 deltaL = forcedInitialStepLength;
774 if ( hpcMode == 1 ) {
776 }
else if ( hpcMode == 2 ) {
783 OOFEM_ERROR(
"HPC Map size must be even number, it contains pairs <node, nodeDof>");
790 for (
int i = 1; i <= nsize; i++ ) {
794 OOFEM_ERROR(
"HPC map size and weight array size mismatch");
849 for (
int _i = 0; _i <
nccdg; _i++ ) {
854 for (
int _j = 1; _j <= _val.
giveSize(); _j++ ) {
868 OOFEM_ERROR(
"Incompatible size of rtolf or rtold params, expected size %d (nccdg)",
nccdg);
872 double _rtol = 1.e-3;
893 }
else if(rst == 1) {
900void CylindricalALM :: convertHPCMap()
924 for (
auto &dman :
domain->giveDofManagers() ) {
925 int jglobnum = dman->giveLabel();
926 for (
int i = 1; i <= size; i++ ) {
929 if ( inode == jglobnum ) {
931 indirectMap.
at(++count) = dman->giveDofWithID(idofid)->giveEquationNumber(dn);
942 if ( count != size ) {
943 OOFEM_WARNING(
"some dofmans/Dofs in HPCarray not recognized");
951 for (
int i = 1; i <= count; i++ ) {
977CylindricalALM :: giveLinearSolver()
997 double deltaL,
double DeltaLambda0,
int neq)
999 double a1 = 0.0, a2 = 0.0, a3 = 0.0, a4, a5;
1017 a1 = eta * eta * XX +
Psi *
Psi * RR;
1018 a2 = RR *
Psi *
Psi * DeltaLambda0 * 2.0
1020 + 2.0 * eta * eta * X_Xt;
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;
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);
1051 double discr = a2 * a2 - 4.0 * a1 * a3;
1052 if ( discr < 0.0 ) {
1053 OOFEM_WARNING(
"discriminant is negative, restarting the step");
1059 discr = sqrt(discr);
1060 double lam1 = ( -a2 + discr ) / 2. / a1;
1061 double lam2 = ( -a2 - discr ) / 2. / a1;
1078 a4 += eta * dX.
at(ind) * deltaX_.
at(ind) + dX.
at(ind) * dX.
at(ind);
1079 a5 += eta * dX.
at(ind) * deltaXt.
at(ind);
1092 if ( cos1 > cos2 ) {
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));
1121 double nom = 0., denom = 0.;
1138 OOFEM_ERROR(
"zero denominator in linearized control");
1141 deltaLambda = (
deltaL - nom ) / denom;
1150 double maxetalim,
double minetalim,
int &ico)
1153 double etaneg = 1.0;
1154 double etamax = 0.0;
1160 for (
int i = 1; i <= istep; i++ ) {
1161 etamax =
max( etamax, eta.
at(i) );
1162 if ( prod.
at(i) >= 0.0 ) {
1166 if ( eta.
at(i) >= etaneg ) {
1179 for (
int i = 1; i <= istep; i++ ) {
1180 if ( prod.
at(i) <= 0.0 ) {
1184 if ( eta.
at(i) > eta.
at(ineg) ) {
1188 if ( eta.
at(i) < eta.
at(ipos) ) {
1196 double etaint = ( prod.
at(ineg) * eta.
at(ipos) - prod.
at(ipos) * eta.
at(ineg) ) / ( prod.
at(ineg) - prod.
at(ipos) );
1198 double etaalt = eta.
at(ipos) + 0.2 * ( eta.
at(ineg) - eta.
at(ipos) );
1199 etaint =
max(etaint, etaalt);
1200 if ( etaint < minetalim ) {
1209 eta.
at(istep + 1) = etaint;
1212 double etamaxstep = amp * etamax;
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;
1218 if ( ( etaextrap <= 0.0 ) || ( etaextrap > etamaxstep ) ) {
1219 eta.
at(istep + 1) = etamaxstep;
1222 if ( ( eta.
at(istep + 1) > maxetalim ) && ( ico == 1 ) ) {
1227 if ( ( eta.
at(istep + 1) > maxetalim ) ) {
1229 eta.
at(istep + 1) = maxetalim;
1238 double &DeltaLambda,
double &DeltaLambdam1,
double &deltaLambda,
1239 double &Lambda,
double &ReachedLambda,
double RR,
double &drProduct,
TimeStep *tStep)
1246 int ls_failed, dl_failed = 0;
1249 int ls_maxiter = 10;
1251 DeltaLambda = DeltaLambdam1 + deltaLambda;
1252 Lambda = ReachedLambda + DeltaLambda;
1253 double deltaLambdaForEta1 = deltaLambda;
1255 double d6, d7, d8, d9;
1262 double e1, e2, d10 = 0.0, d11 = 0.0;
1264 double prevEta, currEta;
1266 FloatArray eta(ls_maxiter + 1), prod(ls_maxiter + 1);
1277 currEta = eta.at(2) = 1.0;
1285 for (
int ils = 2; ils <= ls_maxiter; ils++ ) {
1290 ddX.
add(eta.at(ils) * deltaLambda, deltaXt);
1291 ddX.
add(eta.at(ils), deltaX_);
1296 drProduct *= drProduct;
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;
1319 currEta = eta.at(ils);
1325 currEta = eta.at(ils);
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;
1341 currEta = eta.at(ils + 1);
1343 dl_failed = this->
computeDeltaLambda(deltaLambda, dXm1, deltaXt, deltaX_, R, RR, currEta,
deltaL, DeltaLambdam1, neq);
1345 eta.at(ils + 1) = 1.0;
1346 deltaLambda = deltaLambdaForEta1;
1350 DeltaLambda = DeltaLambdam1 + deltaLambda;
1351 Lambda = ReachedLambda + DeltaLambda;
1353 }
while ( ( _iter < 10 ) && ( fabs( ( currEta - prevEta ) / prevEta ) > 0.01 ) );
1355 if ( ( ls_failed > 1 ) || dl_failed ) {
1364 if ( ls_failed || dl_failed ) {
1366 deltaLambda = deltaLambdaForEta1;
1370 ddX.
add(deltaLambda, deltaXt);
1376 drProduct *= drProduct;
1380 DeltaLambda = DeltaLambdam1 + deltaLambda;
1381 Lambda = ReachedLambda + DeltaLambda;
1383 OOFEM_LOG_INFO(
"CALMLS: Line search - err_id=%d, eta=%e, dlambda=%e\n", ls_failed, 1.0, deltaLambda);
1385 OOFEM_LOG_INFO(
"CALMLS: Line search - err_id=%d, eta=%e, dlambda=%e\n", ls_failed, currEta, deltaLambda);
#define CALM_DEFAULT_NRM_TICKS
#define CALM_RESET_STEP_REDUCE
#define CALM_MAX_REL_ERROR_BOUND
#define _IFT_CylindricalALM_minsteplength
#define _IFT_CylindricalALM_rtolv
#define _IFT_CylindricalALM_rootselectiontype
#define _IFT_CylindricalALM_psi
#define _IFT_CylindricalALM_hpcw
#define _IFT_CylindricalALM_lsearchtol
#define _IFT_CylindricalALM_lsearchamp
#define _IFT_CylindricalALM_miniterations
#define _IFT_CylindricalALM_initialsteplength
#define _IFT_CylindricalALM_forcedinitialsteplength
#define _IFT_CylindricalALM_hpcmode
#define _IFT_CylindricalALM_lstype
#define _IFT_CylindricalALM_rtold
#define _IFT_CylindricalALM_rtolf
#define _IFT_CylindricalALM_manrmsteps
#define _IFT_CylindricalALM_reqiterations
#define _IFT_CylindricalALM_nccdg
#define calm_SMALL_ERROR_NUM
#define _IFT_CylindricalALM_maxiter
#define _IFT_CylindricalALM_lsearchmaxeta
#define _IFT_CylindricalALM_hpc
#define _IFT_CylindricalALM_steplength
#define _IFT_CylindricalALM_ccdg
#define _IFT_CylindricalALM_maxrestarts
#define _IFT_CylindricalALM_linesearch
#define REGISTER_SparseNonLinearSystemNM(class)
SparseLinearSystemNM * giveLinearSolver() override
FloatArray rtold
Relative iterative displacement change tolerance for each group.
int minIterations
Minimum hard number of iteration.s.
FloatArray calm_HPCDmanWeightSrcArray
Input array of dofman weights (for hpcmode 2).
ParallelContext * parallel_context
Parallel context for computing norms, dot products and such.
std ::set< DofIDItem > __DofIDSet
FloatArray calm_HPCWeights
double ls_tolerance
Line search tolerance.
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.
calm_NR_ModeType calm_NR_Mode
@ calml_hpc
Linearized ALM (only displacements), taking into account only selected dofs with given weight.
@ calm_hpc_on
Full ALM with quadratic constrain, taking into account only selected dofs.
@ calm_hpc_off
Full ALM with quadratic constrain and all dofs.
calm_NR_ModeType calm_NR_OldMode
int numberOfRequiredIterations
double amplifFactor
Line search amplification factor.
int calm_hpc_init
Variables for HyperPlaneControl.
int lsFlag
Line search flag.
int nccdg
Number of convergence criteria dof groups.
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.
@ calm_modifiedNRM
Keeps the old tangent.
@ calm_accelNRM
Updates the tangent after a few steps.
@ calm_fullNRM
Updates the tangent every iteration.
IntArray calm_HPCDmanDofSrcArray
Input array containing dofmanagers and corresponding dof numbers under indirect control.
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)
calm_ControlType calm_Control
LinSystSolverType solverType
linear system solver ID.
std ::unique_ptr< SparseLinearSystemNM > linSolver
Linear system solver.
void search(int istep, FloatArray &prod, FloatArray &eta, double amp, double maxeta, double mineta, int &status)
IntArray calm_HPCIndirectDofMask
Array containing equation numbers of dofs under indirect control.
FloatArray old_dX
previous increment of dX, needed by root selection type 1
std ::vector< __DofIDSet > ccDofGroups
Convergence criteria dof groups.
double maxEta
Line search parameters (limits).
RootSelectionType rootselectiontype
Root selection type.
FloatArray rtolf
Relative unbalanced force tolerance for each group.
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.
Index giveSize() const
Returns the size of receiver.
void zero()
Zeroes all coefficients of receiver.
void add(const FloatArray &src)
void subtract(const FloatArray &src)
Domain * domain
Pointer to domain.
EngngModel * engngModel
Pointer to engineering model.
referenceLoadInputModeType
void incrementSubStepNumber()
Increments receiver's substep number.
void incrementStateCounter()
Updates solution state counter.
int giveNumber()
Returns receiver's number.
#define OOFEM_WARNING(...)
#define OOFEM_LOG_INFO(...)
static FloatArray Vec2(const double &a, const double &b)
@ Element_local
Element is local, there are no contributions from other domains to this element.
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1).
ClassFactory & classFactory
static FloatArray Vec4(const double &a, const double &b, const double &c, const double &d)
@ CIO_IOERR
General IO error.