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()
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() );
114 FloatArray rhs, deltaXt, deltaX_, dXm1, XInitial;
117 double XX, RR, RR0, XR, p = 0.0;
118 double deltaLambda, Lambda, eta, DeltaLambdam1, DeltaLambda = 0.0;
119 double drProduct = 0.0;
125 bool converged, errorOutOfRangeFlag;
130 OOFEM_LOG_INFO(
"CALMLS: Iteration LoadLevel ForceError DisplError \n");
131 OOFEM_LOG_INFO(
"----------------------------------------------------------------------------\n");
134 for ( i = 1; i <=
nccdg; i++ ) {
138 OOFEM_LOG_INFO(
"\n__________________________________________________________\n");
207 p = sqrt(XX +
Psi *
Psi * RR);
212 for ( i = 1; i <= HPsize; i++ ) {
214 _XX += deltaXt.
at(ind) * deltaXt.
at(ind);
215 _RR += R.
at(ind) * R.
at(ind);
222 _XX = collected_XXRR(0);
223 _RR = collected_XXRR(1);
225 p = sqrt(_XX +
Psi *
Psi * _RR);
229 for ( i = 1; i <= HPsize; i++ ) {
243 Lambda = ReachedLambda;
244 DeltaLambda = deltaLambda =
sgn(XR) *
deltaL / p;
245 Lambda += DeltaLambda;
251 rhs.
times(DeltaLambda);
269 DeltaLambdam1 = DeltaLambda;
343 if ( this->
lsFlag && ( nite != 1 ) ) {
350 DeltaLambda, DeltaLambdam1, deltaLambda, Lambda, ReachedLambda,
351 RR, drProduct, tStep);
357 ddX.
add(eta * deltaLambda, deltaXt);
358 ddX.
add(eta, deltaX_);
365 drProduct *= drProduct;
371 DeltaLambda = DeltaLambdam1 + deltaLambda;
372 Lambda = ReachedLambda + DeltaLambda;
384 converged = this->
checkConvergence(R, R0, F, X, ddX, Lambda, RR0, RR, drProduct,
385 internalForcesEBENorm, nite, errorOutOfRangeFlag);
386 if ( ( nite >=
nsmax ) || errorOutOfRangeFlag ) {
436 bk = DeltaLambda * RDR / ( DR * DR );
472 ReachedLambda = Lambda;
480 double Lambda,
double RR0,
double RR,
double drProduct,
481 const FloatArray &internalForcesEBENorm,
int nite,
bool &errorOutOfRange)
489 double forceErr, dispErr;
496 errorOutOfRange =
false;
508 forceErr = dispErr = 0.0;
512 dg_totalLoadLevel.zero();
516 if ( !dman->isLocal() ) {
521 for (
Dof *_idofptr: *dman ) {
523 for (
int _dg = 1; _dg <= _ng; _dg++ ) {
526 int _eq = _idofptr->giveEquationNumber(dn);
531 dg_forceErr.at(_dg) += rhs.
at(_eq) * rhs.
at(_eq);
532 dg_dispErr.at(_dg) += ddX.
at(_eq) * ddX.
at(_eq);
535 dg_totalLoadLevel.at(_dg) += R0->
at(_eq) * R0->
at(_eq);
538 dg_totalLoadLevel.at(_dg) += R.
at(_eq) * R.
at(_eq) * Lambda * Lambda;
539 dg_totalDisp.
at(_dg) += X.
at(_eq) * X.
at(_eq);
552 for (
int _idofman = 1; _idofman <= elem->giveNumberOfInternalDofManagers(); _idofman++ ) {
554 for (
Dof *_idofptr: *elem->giveInternalDofManager(_idofman) ) {
556 for (
int _dg = 1; _dg <= _ng; _dg++ ) {
559 int _eq = _idofptr->giveEquationNumber(dn);
564 dg_forceErr.at(_dg) += rhs.
at(_eq) * rhs.
at(_eq);
565 dg_dispErr.at(_dg) += ddX.
at(_eq) * ddX.
at(_eq);
568 dg_totalLoadLevel.at(_dg) += R0->
at(_eq) * R0->
at(_eq);
571 dg_totalLoadLevel.at(_dg) += R.
at(_eq) * R.
at(_eq) * Lambda * Lambda;
572 dg_totalDisp.
at(_dg) += X.
at(_eq) * X.
at(_eq);
582 dg_forceErr = collectiveErr;
584 dg_dispErr = collectiveErr;
586 dg_totalLoadLevel = collectiveErr;
588 dg_totalDisp = collectiveErr;
592 for (
int _dg = 1; _dg <= _ng; _dg++ ) {
595 dg_forceErr.at(_dg) = sqrt( dg_forceErr.at(_dg) );
597 dg_forceErr.at(_dg) = sqrt( dg_forceErr.at(_dg) / dg_totalLoadLevel.at(_dg) );
604 dg_dispErr.at(_dg) = sqrt( dg_dispErr.at(_dg) );
606 dg_dispErr.at(_dg) = sqrt( dg_dispErr.at(_dg) / dg_totalDisp.
at(_dg) );
611 errorOutOfRange =
true;
614 if ( ( fabs( dg_forceErr.at(_dg) ) >
rtolf.
at(_dg) ) || ( fabs( dg_dispErr.at(_dg) ) >
rtold.
at(_dg) ) ) {
619 OOFEM_LOG_INFO(
"%-15e %-15e ", dg_forceErr.at(_dg), dg_dispErr.at(_dg) );
633 forceErr *= forceErr;
637 double eNorm = internalForcesEBENorm.
sum();
640 forceErr = sqrt( forceErr / ( RR0 + RR * Lambda * Lambda ) );
642 forceErr = sqrt(forceErr / eNorm);
644 forceErr = sqrt(forceErr);
653 dispErr = drProduct / dXX;
654 dispErr = sqrt(dispErr);
659 errorOutOfRange =
true;
662 if ( ( fabs(forceErr) >
rtolf.
at(1) ) || ( fabs(dispErr) >
rtold.
at(1) ) ) {
666 OOFEM_LOG_INFO(
"CALMLS: %-15d %-15e %-15e %-15e\n", nite, Lambda, forceErr, dispErr);
680 double initialStepLength, forcedInitialStepLength;
708 deltaL = initialStepLength;
712 forcedInitialStepLength = 0.;
714 if ( forcedInitialStepLength > 0. ) {
715 deltaL = forcedInitialStepLength;
767 if ( hpcMode == 1 ) {
769 }
else if ( hpcMode == 2 ) {
776 OOFEM_ERROR(
"HPC Map size must be even number, it contains pairs <node, nodeDof>");
783 for (
int i = 1; i <= nsize; i++ ) {
787 OOFEM_ERROR(
"HPC map size and weight array size mismatch");
842 for (
int _i = 0; _i <
nccdg; _i++ ) {
847 for (
int _j = 1; _j <= _val.
giveSize(); _j++ ) {
861 OOFEM_ERROR(
"Incompatible size of rtolf or rtold params, expected size %d (nccdg)", nccdg);
865 double _rtol = 1.e-3;
911 int jglobnum = dman->giveLabel();
912 for (
int i = 1; i <= size; i++ ) {
915 if ( inode == jglobnum ) {
917 indirectMap.
at(++count) = dman->giveDofWithID(idofid)->giveEquationNumber(dn);
928 if ( count != size ) {
929 OOFEM_WARNING(
"some dofmans/Dofs in HPCarray not recognized");
937 for (
int i = 1; i <= count; i++ ) {
989 double deltaL,
double DeltaLambda0,
int neq)
991 double a1 = 0.0, a2 = 0.0, a3 = 0.0, a4, a5;
1009 a1 = eta * eta * XX +
Psi *
Psi * RR;
1010 a2 = RR *
Psi *
Psi * DeltaLambda0 * 2.0
1012 + 2.0 * eta * eta * X_Xt;
1016 + DeltaLambda0 * DeltaLambda0 * RR *
Psi *
Psi - deltaL *
deltaL;
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;
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;
1043 double discr = a2 * a2 - 4.0 * a1 * a3;
1044 if ( discr < 0.0 ) {
1045 OOFEM_ERROR(
"discriminant is negative, solution failed");
1048 discr = sqrt(discr);
1049 double lam1 = ( -a2 + discr ) / 2. / a1;
1050 double lam2 = ( -a2 - discr ) / 2. / a1;
1067 a4 += eta * dX.
at(ind) * deltaX_.
at(ind) + dX.
at(ind) * dX.
at(ind);
1068 a5 += eta * dX.
at(ind) * deltaXt.
at(ind);
1079 double cos1 = ( a4 + a5 * lam1 ) / deltaL / deltaL;
1080 double cos2 = ( a4 + a5 * lam2 ) / deltaL / deltaL;
1081 if ( cos1 > cos2 ) {
1090 double nom = 0., denom = 0.;
1107 OOFEM_ERROR(
"zero denominator in linearized control");
1110 deltaLambda = ( deltaL - nom ) / denom;
1119 double maxetalim,
double minetalim,
int &ico)
1122 double etaneg = 1.0;
1123 double etamax = 0.0;
1129 for (
int i = 1; i <= istep; i++ ) {
1130 etamax =
max( etamax, eta.
at(i) );
1131 if ( prod.
at(i) >= 0.0 ) {
1135 if ( eta.
at(i) >= etaneg ) {
1148 for (
int i = 1; i <= istep; i++ ) {
1149 if ( prod.
at(i) <= 0.0 ) {
1153 if ( eta.
at(i) > eta.
at(ineg) ) {
1157 if ( eta.
at(i) < eta.
at(ipos) ) {
1165 double etaint = ( prod.
at(ineg) * eta.
at(ipos) - prod.
at(ipos) * eta.
at(ineg) ) / ( prod.
at(ineg) - prod.
at(ipos) );
1167 double etaalt = eta.
at(ipos) + 0.2 * ( eta.
at(ineg) - eta.
at(ipos) );
1168 etaint =
max(etaint, etaalt);
1169 if ( etaint < minetalim ) {
1178 eta.
at(istep + 1) = etaint;
1181 double etamaxstep = amp * etamax;
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;
1187 if ( ( etaextrap <= 0.0 ) || ( etaextrap > etamaxstep ) ) {
1188 eta.
at(istep + 1) = etamaxstep;
1191 if ( ( eta.
at(istep + 1) > maxetalim ) && ( ico == 1 ) ) {
1196 if ( ( eta.
at(istep + 1) > maxetalim ) ) {
1198 eta.
at(istep + 1) = maxetalim;
1207 double &DeltaLambda,
double &DeltaLambdam1,
double &deltaLambda,
1208 double &Lambda,
double &ReachedLambda,
double RR,
double &drProduct,
TimeStep *tStep)
1215 int ls_failed, dl_failed = 0;
1218 int ls_maxiter = 10;
1220 DeltaLambda = DeltaLambdam1 + deltaLambda;
1221 Lambda = ReachedLambda + DeltaLambda;
1222 double deltaLambdaForEta1 = deltaLambda;
1224 double d6, d7, d8, d9;
1231 double e1, e2, d10 = 0.0, d11 = 0.0;
1233 double prevEta, currEta;
1235 FloatArray eta(ls_maxiter + 1), prod(ls_maxiter + 1);
1246 currEta = eta.at(2) = 1.0;
1254 for (
int ils = 2; ils <= ls_maxiter; ils++ ) {
1259 ddX.
add(eta.at(ils) * deltaLambda, deltaXt);
1260 ddX.
add(eta.at(ils), deltaX_);
1265 drProduct *= drProduct;
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;
1288 currEta = eta.at(ils);
1294 currEta = eta.at(ils);
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;
1310 currEta = eta.at(ils + 1);
1312 dl_failed = this->
computeDeltaLambda(deltaLambda, dXm1, deltaXt, deltaX_, R, RR, currEta,
deltaL, DeltaLambdam1, neq);
1314 eta.at(ils + 1) = 1.0;
1315 deltaLambda = deltaLambdaForEta1;
1319 DeltaLambda = DeltaLambdam1 + deltaLambda;
1320 Lambda = ReachedLambda + DeltaLambda;
1322 }
while ( ( _iter < 10 ) && ( fabs( ( currEta - prevEta ) / prevEta ) > 0.01 ) );
1324 if ( ( ls_failed > 1 ) || dl_failed ) {
1333 if ( ls_failed || dl_failed ) {
1335 deltaLambda = deltaLambdaForEta1;
1339 ddX.
add(deltaLambda, deltaXt);
1345 drProduct *= drProduct;
1349 DeltaLambda = DeltaLambdam1 + deltaLambda;
1350 Lambda = ReachedLambda + DeltaLambda;
1352 OOFEM_LOG_INFO(
"CALMLS: Line search - err_id=%d, eta=%e, dlambda=%e\n", ls_failed, 1.0, deltaLambda);
1354 OOFEM_LOG_INFO(
"CALMLS: Line search - err_id=%d, eta=%e, dlambda=%e\n", ls_failed, currEta, deltaLambda);
virtual ~CylindricalALM()
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.
#define NM_Success
Numerical method exited with success.
#define _IFT_CylindricalALM_minsteplength
int nccdg
Number of convergence criteria dof groups.
virtual void applyPerturbation(FloatArray *displacement)
bool isLocal(DofManager *dman)
virtual IRResultType initializeFrom(InputRecord *ir)
Base class for all matrices stored in sparse format.
#define _IFT_CylindricalALM_reqiterations
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 .
#define _IFT_CylindricalALM_initialsteplength
The purpose of DataStream abstract class is to allow to store/restore context to different streams...
ExportModuleManager * giveExportModuleManager()
Returns receiver's export module manager.
double & at(int i)
Coefficient access function.
#define _IFT_CylindricalALM_nccdg
int max(int i, int j)
Returns bigger value form two given decimals.
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)
double sgn(double i)
Returns the signum of given value (if value is < 0 returns -1, otherwise returns 1) ...
FloatArray rtolf
Relative unbalanced force tolerance for each group.
This base class is an abstraction for all numerical methods solving sparse linear system of equations...
void clear()
Clears receiver (zero size).
#define _IFT_CylindricalALM_psi
REGISTER_SparseNonLinearSystemNM(CylindricalALM)
#define _IFT_CylindricalALM_hpc
#define _IFT_CylindricalALM_hpcmode
virtual SparseLinearSystemNM * giveLinearSolver()
Constructs (if necessary) and returns a linear solver.
Linearized ALM (only displacements), taking into account only selected dofs with given weight...
void incrementStateCounter()
Updates solution state counter.
void doOutput(TimeStep *tStep, bool substepFlag=false)
Writes the output.
#define _IFT_CylindricalALM_ccdg
void search(int istep, FloatArray &prod, FloatArray &eta, double amp, double maxeta, double mineta, int &status)
std::vector< std::unique_ptr< DofManager > > & giveDofManagers()
Full ALM with quadratic constrain and all dofs.
FloatArray calm_HPCWeights
unsigned long NM_Status
Mask defining NumMetod Status; which can be asked after finishing computation by Numerical Method...
Class implementing an array of integers.
int & at(int i)
Coefficient access function.
virtual int read(int *data, int count)=0
Reads count integer values into array pointed by data.
#define calm_SMALL_ERROR_NUM
calm_ControlType calm_Control
#define CALM_DEFAULT_NRM_TICKS
int lsFlag
Line search flag.
virtual void initStepIncrements()
Initializes solution of new time step.
void incrementSubStepNumber()
Increments receiver's substep number.
#define NM_NoSuccess
Numerical method failed to solve problem.
#define _IFT_CylindricalALM_maxrestarts
Domain * domain
Pointer to domain.
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.
double amplifFactor
Line search amplification factor.
double localDotProduct(const FloatArray &a, const FloatArray &b)
Dot product for a locally distributed array.
#define _IFT_CylindricalALM_maxiter
#define _IFT_CylindricalALM_rtold
int giveNumber()
Returns receiver's number.
#define OOFEM_LOG_INFO(...)
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.
virtual contextIOResultType saveContext(DataStream &stream, ContextMode mode, void *obj=NULL)
#define _IFT_CylindricalALM_forcedinitialsteplength
std::vector< __DofIDSet > ccDofGroups
Convergence criteria dof groups.
#define _IFT_CylindricalALM_rtolv
void clear()
Clears the array (zero size).
DofIDItem
Type representing particular dof type.
virtual void updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d)
Updates components mapped to numerical method if necessary during solution process.
#define _IFT_CylindricalALM_lsearchmaxeta
Implementation of sparse nonlinear solver with indirect control.
FloatArray rtold
Relative iterative displacement change tolerance for each group.
calm_NR_ModeType calm_NR_OldMode
#define CALM_RESET_STEP_REDUCE
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.
void resize(int n)
Checks size of receiver towards requested bounds.
#define _IFT_CylindricalALM_miniterations
FloatArray calm_HPCDmanWeightSrcArray
Input array of dofman weights (for hpcmode 2).
int numberOfRequiredIterations
int minIterations
Minimum hard number of iteration.s.
double maxEta
Line search parameters (limits).
Initializes the variable VERBOSE, in order to get a few intermediate messages on screen: beginning an...
Class representing vector of real numbers.
SparseLinearSystemNM * createSparseLinSolver(LinSystSolverType st, Domain *d, EngngModel *m)
Creates new instance of SparseLinearSystemNM corresponding to given type.
Full ALM with quadratic constrain, taking into account only selected dofs.
calm_NR_ModeType calm_NR_Mode
IRResultType initializeFrom(InputRecord *ir)
Element is local, there are no contributions from other domains to this element.
#define _IFT_CylindricalALM_lstype
IRResultType
Type defining the return values of InputRecord reading operations.
#define _IFT_CylindricalALM_linesearch
#define _IFT_CylindricalALM_lsearchamp
ParallelContext * parallel_context
Parallel context for computing norms, dot products and such.
IntArray calm_HPCIndirectDofMask
Array containing equation numbers of dofs under indirect control.
#define CALM_MAX_REL_ERROR_BOUND
void zero()
Zeroes all coefficients of receiver.
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.
void times(double s)
Multiplies receiver with scalar.
#define _IFT_CylindricalALM_rtolf
Updates the tangent every iteration.
double accumulate(double local)
Accumulates the global value.
ClassFactory & classFactory
long ContextMode
Context mode (mask), defining the type of information written/read to/from context.
IntArray calm_HPCDmanDofSrcArray
Input array containing dofmanagers and corresponding dof numbers under indirect control.
double ls_tolerance
Line search tolerance.
std::vector< std::unique_ptr< Element > > & giveElements()
Abstract base class representing the "problem" under consideration.
virtual contextIOResultType restoreContext(DataStream &stream, ContextMode mode, void *obj=NULL)
Updates the tangent after a few steps.
int giveSize() const
Returns the size of receiver.
the oofem namespace is to define a context or scope in which all oofem names are defined.
#define _IFT_CylindricalALM_lsearchtol
Abstract class Dof represents Degree Of Freedom in finite element mesh.
#define _IFT_CylindricalALM_hpcw
virtual IRResultType initializeFrom(InputRecord *ir)
EngngModel * engngModel
Pointer to engineering model.
double localNorm(const FloatArray &src)
Norm for a locally distributed array.
#define OOFEM_WARNING(...)
int calm_hpc_init
Variables for HyperPlaneControl.
Class representing solution step.
LinSystSolverType solverType
linear system solver ID.
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.
#define _IFT_CylindricalALM_manrmsteps
std::set< DofIDItem > __DofIDSet
#define _IFT_CylindricalALM_steplength
void resize(int s)
Resizes receiver towards requested size.