49 #define ERROR_NORM_SMALL_NUM 1.e-6 50 #define MAX_REL_ERROR_BOUND 1.e20 59 if ( this->dofIdArray.contains( (
int)
id ) ) {
60 return prescribed ? dof->__givePrescribedEquationNumber() : dof->__giveEquationNumber();
68 prescribed(false), numEqs(0), numPresEqs(0), dofIdArray(0)
94 for (
int i = 0; i < numDofIdGroups; i++ ) {
97 for (
int j = 0; j < sz; j++) {
98 int pos =
idPos.
at(i*2 + 1) + j;
108 stiffnessMatrixList(numberings.size()),
109 fIntList(numberings.size()),
110 fExtList(numberings.size()),
111 locArrayList(numberings.size()),
112 X(numberings.size()),
113 dX(numberings.size()),
114 ddX(numberings.size())
116 for (
int dG = 0; dG < (int)numberings.size(); dG++ ) {
125 IntArray nodalArray, ids, locationArray;
126 locationArray.
clear();
129 dman->giveCompleteLocationArray(nodalArray, s);
133 for (
int i = 1; i <= elem->giveNumberOfInternalDofManagers(); i++ ) {
134 elem->giveInternalDofManDofIDMask(i, ids);
135 elem->giveInternalDofManager(i)->giveLocationArray(ids, nodalArray, s);
144 for (
int i = 1; i <= nonZeroMask.
giveSize(); i++ ) {
145 condensedLocationArray.
at(i) = locationArray.
at( nonZeroMask.
at(i) );
162 bool converged, errorOutOfRangeFlag;
163 ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
165 if ( engngModel->giveProblemScale() ==
macroScale ) {
167 if ( rtolf.at(1) > 0.0 ) {
170 if ( rtold.at(1) > 0.0 ) {
173 OOFEM_LOG_INFO(
"\n----------------------------------------------------------------------------\n");
178 this->giveLinearSolver();
186 RRTtotal = parallel_context->
localNorm(RT);
187 RRTtotal *= RRTtotal;
199 DofGrouping dg(this->UnknownNumberingSchemeList, this->domain);
202 int numDofIdGroups = (int)this->UnknownNumberingSchemeList.size();
204 for (
int dG = 0; dG < numDofIdGroups; dG++ ) {
206 RRT(dG) = dg.
fExtList[dG].computeSquaredNorm();
209 for (
int nStaggeredIter = 0;; ++nStaggeredIter) {
212 for (
int dG = 0; dG < (int)this->UnknownNumberingSchemeList.size(); dG++ ) {
215 engngModel->updateComponent(tStep,
NonLinearLhs, domain);
218 if ( this->prescribedDofsFlag ) {
219 if ( !prescribedEqsInitFlag ) {
220 this->initPrescribedEqs();
222 applyConstraintsToStiffness(k);
225 for (nite = 0;; ++nite) {
227 engngModel->updateComponent(tStep,
InternalRhs, domain);
237 if ( this->prescribedDofsFlag ) {
238 this->applyConstraintsToLoadIncrement(nite, k, rhs, rlm, tStep);
242 IntArray &idArray = UnknownNumberingSchemeList[dG].dofIdArray;
243 converged = this->checkConvergenceDofIdArray(RT, F, RHS, ddXtotal, Xtotal, RRTtotal, internalForcesEBENorm, nite, errorOutOfRangeFlag, tStep, idArray);
246 if ( errorOutOfRangeFlag ) {
248 OOFEM_WARNING(
"Divergence reached after %d iterations", nite);
250 }
else if ( converged && ( nite >= minIterations ) ) {
253 }
else if ( nite >= nsmax ) {
258 if ( nite > 0 || !mCalcStiffBeforeRes ) {
259 if ( NR_Mode == nrsolverFullNRM || ( NR_Mode == nrsolverAccelNRM && (nite % MANRMSteps) == 0 ) ) {
260 engngModel->updateComponent(tStep,
NonLinearLhs, domain);
266 if ( ( nite == 0 ) && ( deltaL < 1.0 ) ) {
277 if ( this->lsFlag && ( nite > 0 ) ) {
281 this->giveLineSearchSolver()->solve( dg.
X[dG], dg.
ddX[dG], dg.
fIntList[dG], dg.
fExtList[dG], R0, prescribedEqs, 1.0, eta, LSstatus, tStep);
282 }
else if ( this->constrainedNRFlag && ( nite > this->constrainedNRminiter ) ) {
283 if ( this->forceErrVec.computeSquaredNorm() > this->forceErrVecOld.computeSquaredNorm() ) {
284 OOFEM_LOG_INFO(
"Constraining increment to be %e times full increment...\n", this->constrainedNRalpha);
285 dg.
ddX[dG].times(this->constrainedNRalpha);
288 dg.
X[dG].add(dg.
ddX[dG]);
289 dg.
dX[dG].add(dg.
ddX[dG]);
301 engngModel->giveExportModuleManager()->doOutput(tStep,
true);
310 converged = this->checkConvergence(RT, F, RHS, ddXtotal, Xtotal, RRTtotal, internalForcesEBENorm, nStaggeredIter, errorOutOfRangeFlag);
311 if ( converged && ( nStaggeredIter >= minIterations ) ) {
318 for (
int i = 1; i <= numberOfPrescribedDofs; i++ ) {
319 R.
at( prescribedEqs.at(i) ) = F.
at( prescribedEqs.at(i) ) - R0->
at( prescribedEqs.at(i) ) - R.
at( prescribedEqs.at(i) );
322 for (
int i = 1; i <= numberOfPrescribedDofs; i++ ) {
323 R.
at( prescribedEqs.at(i) ) = F.
at( prescribedEqs.at(i) ) - R.
at( prescribedEqs.at(i) );
327 this->lastReactions.resize(numberOfPrescribedDofs);
330 if ( numberOfPrescribedDofs ) {
336 for (
int i = 1; i <= numberOfPrescribedDofs; i++ ) {
337 reaction = R->
at( prescribedEqs.at(i) );
339 reaction += R0->
at( prescribedEqs.at(i) );
341 lastReactions.at(i) = reaction;
342 OOFEM_LOG_INFO(
"StaggeredSolver: %-15d %-15d %-+15.5e %-+15.5e\n", prescribedDofs.at(2 * i - 1), prescribedDofs.at(2 * i),
343 X.at( prescribedEqs.at(i) ), reaction);
359 double forceErr, dispErr;
360 FloatArray dg_forceErr, dg_dispErr, dg_totalLoadLevel, dg_totalDisp;
363 ParallelContext *parallel_context = engngModel->giveParallelContext( this->domain->giveNumber() );
376 errorOutOfRange =
false;
379 if ( this->constrainedNRFlag ) {
380 this->forceErrVecOld = this->forceErrVec;
381 this->forceErrVec.resize( internalForcesEBENorm.
giveSize() );
385 if ( internalForcesEBENorm.
giveSize() > 1 ) {
386 int nccdg = this->domain->giveMaxDofID();
391 dg_forceErr.
resize(nccdg);
395 dg_totalLoadLevel.
resize(nccdg);
396 dg_totalLoadLevel.
zero();
397 dg_totalDisp.
resize(nccdg);
400 for (
auto &dofman : domain->giveDofManagers() ) {
401 if ( !parallel_context->
isLocal(dofman.get()) ) {
406 for (
Dof *dof: *dofman ) {
407 if ( !dof->isPrimaryDof() ) {
410 int eq = dof->giveEquationNumber(dn);
411 int dofid = dof->giveDofID();
416 dg_forceErr.
at(dofid) += rhs.
at(eq) * rhs.
at(eq);
417 dg_dispErr.
at(dofid) += ddX.
at(eq) * ddX.
at(eq);
418 dg_totalLoadLevel.
at(dofid) += RT.
at(eq) * RT.
at(eq);
419 dg_totalDisp.
at(dofid) += X.
at(eq) * X.
at(eq);
420 idsInUse.
at(dofid) = 1;
425 for (
auto &elem : domain->giveElements() ) {
431 for (
int idofman = 1; idofman <= elem->giveNumberOfInternalDofManagers(); idofman++ ) {
432 DofManager *dofman = elem->giveInternalDofManager(idofman);
434 for (
Dof *dof: *dofman ) {
435 if ( !dof->isPrimaryDof() ) {
438 int eq = dof->giveEquationNumber(dn);
439 int dofid = dof->giveDofID();
445 dg_forceErr.
at(dofid) += rhs.
at(eq) * rhs.
at(eq);
446 dg_dispErr.
at(dofid) += ddX.
at(eq) * ddX.
at(eq);
447 dg_totalLoadLevel.
at(dofid) += RT.
at(eq) * RT.
at(eq);
448 dg_totalDisp.
at(dofid) += X.
at(eq) * X.
at(eq);
449 idsInUse.
at(dofid) = 1;
455 for (
auto &bc : domain->giveBcs() ) {
457 for (
int idofman = 1; idofman <= bc->giveNumberOfInternalDofManagers(); idofman++ ) {
458 DofManager *dofman = bc->giveInternalDofManager(idofman);
460 for (
Dof *dof: *dofman ) {
461 if ( !dof->isPrimaryDof() ) {
464 int eq = dof->giveEquationNumber(dn);
465 int dofid = dof->giveDofID();
471 dg_forceErr.
at(dofid) += rhs.
at(eq) * rhs.
at(eq);
472 dg_dispErr.
at(dofid) += ddX.
at(eq) * ddX.
at(eq);
473 dg_totalLoadLevel.
at(dofid) += RT.
at(eq) * RT.
at(eq);
474 dg_totalDisp.
at(dofid) += X.
at(eq) * X.
at(eq);
475 idsInUse.
at(dofid) = 1;
482 parallel_context->
accumulate(dg_forceErr, collectiveErr);
483 dg_forceErr = collectiveErr;
484 parallel_context->
accumulate(dg_dispErr, collectiveErr);
485 dg_dispErr = collectiveErr;
486 parallel_context->
accumulate(dg_totalLoadLevel, collectiveErr);
487 dg_totalLoadLevel = collectiveErr;
488 parallel_context->
accumulate(dg_totalDisp, collectiveErr);
489 dg_totalDisp = collectiveErr;
494 for (
int dg = 1; dg <= nccdg; dg++ ) {
495 bool zeroFNorm =
false, zeroDNorm =
false;
497 if ( !idsInUse.
at(dg) ) {
508 if ( rtolf.at(1) > 0.0 ) {
511 forceErr = sqrt( dg_forceErr.
at(dg) / ( dg_totalLoadLevel.
at(dg) + internalForcesEBENorm.
at(dg) ) );
516 forceErr = sqrt( dg_forceErr.
at(dg) );
520 errorOutOfRange =
true;
522 if ( forceErr > rtolf.at(1) ) {
528 if ( this->constrainedNRFlag ) {
529 forceErrVec.at(dg) = forceErr;
533 if ( rtold.at(1) > 0.0 ) {
536 dispErr = sqrt( dg_dispErr.
at(dg) / dg_totalDisp.
at(dg) );
541 dispErr = sqrt( dg_dispErr.
at(dg) );
544 errorOutOfRange =
true;
546 if ( dispErr > rtold.at(1) ) {
557 if ( engngModel->giveProblemScale() ==
macroScale ) {
563 forceErr = parallel_context->
localNorm(rhs);
564 forceErr *= forceErr;
570 if ( rtolf.at(1) > 0.0 ) {
573 forceErr = sqrt( forceErr / ( RRT + internalForcesEBENorm.
at(1) ) );
575 forceErr = sqrt(forceErr);
578 errorOutOfRange =
true;
580 if ( fabs(forceErr) > rtolf.at(1) ) {
585 if ( this->constrainedNRFlag ) {
587 forceErrVec.at(1) = forceErr;
591 if ( rtold.at(1) > 0.0 ) {
595 dispErr = sqrt(dXdX / dXX);
597 dispErr = sqrt(dXdX);
600 errorOutOfRange =
true;
602 if ( fabs(dispErr) > rtold.at(1) ) {
bool contains(int value) const
std::vector< std::unique_ptr< SparseMtrx > > stiffnessMatrixList
The representation of EngngModel default unknown numbering.
#define NM_Success
Numerical method exited with success.
std::vector< CustomEquationNumbering > UnknownNumberingSchemeList
bool isLocal(DofManager *dman)
Base class for all matrices stored in sparse format.
This class implements Newton-Raphson Method, derived from abstract NumericalMethod class for solving ...
StaggeredSolver(Domain *d, EngngModel *m)
void zero()
Sets all component to zero.
double & at(int i)
Coefficient access function.
REGISTER_SparseNonLinearSystemNM(CylindricalALM)
std::vector< FloatArray > fIntList
virtual IRResultType initializeFrom(InputRecord *ir)
#define MAX_REL_ERROR_BOUND
void incrementStateCounter()
Updates solution state counter.
Base class for dof managers.
std::vector< std::unique_ptr< DofManager > > & giveDofManagers()
bool checkConvergenceDofIdArray(FloatArray &RT, FloatArray &F, FloatArray &rhs, FloatArray &ddX, FloatArray &X, double RRT, const FloatArray &internalForcesEBENorm, int nite, bool &errorOutOfRange, TimeStep *tStep, IntArray &dofIdArray)
void findNonzeros(const IntArray &logical)
Finds all indices where the input array is nonzero.
unsigned long NM_Status
Mask defining NumMetod Status; which can be asked after finishing computation by Numerical Method...
#define OOFEM_LOG_DEBUG(...)
Class implementing an array of integers.
int & at(int i)
Coefficient access function.
virtual SparseMtrx * giveSubMatrix(const IntArray &rows, const IntArray &cols)
virtual IRResultType initializeFrom(InputRecord *ir)
DofGrouping(const std::vector< CustomEquationNumbering > &numberings, Domain *m)
void beDifferenceOf(const FloatArray &a, const FloatArray &b)
Sets receiver to be a - b.
std::vector< FloatArray > fExtList
void incrementSubStepNumber()
Increments receiver's substep number.
#define NM_NoSuccess
Numerical method failed to solve problem.
std::vector< FloatArray > ddX
#define _IFT_StaggeredSolver_DofIdList
CustomEquationNumbering()
#define OOFEM_LOG_INFO(...)
void clear()
Clears the array (zero size).
DofIDItem
Type representing particular dof type.
Abstract base class allowing to control the way, how equations are assigned to individual DOFs...
referenceLoadInputModeType
The following parameter allows to specify how the reference load vector is obtained from given totalL...
std::vector< FloatArray > dX
void resize(int n)
Checks size of receiver towards requested bounds.
#define ERROR_NORM_SMALL_NUM
Class representing vector of real numbers.
Element is local, there are no contributions from other domains to this element.
IRResultType
Type defining the return values of InputRecord reading operations.
void giveTotalLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, Domain *d)
void assemble(const FloatArray &fe, const IntArray &loc)
Assembles the array fe (typically, the load vector of a finite element) into the receiver, using loc as location array.
This class provides an communication context for distributed memory parallelism.
void followedBy(const IntArray &b, int allocChunk=0)
Appends array b at the end of receiver.
void zero()
Zeroes all coefficients of receiver.
double accumulate(double local)
Accumulates the global value.
std::string __DofIDItemToString(DofIDItem _value)
std::vector< std::unique_ptr< Element > > & giveElements()
Abstract base class representing the "problem" under consideration.
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.
virtual NM_Status solve(SparseMtrx &k, FloatArray &R, FloatArray *R0, FloatArray &X, FloatArray &dX, FloatArray &F, const FloatArray &internalForcesEBENorm, double &l, referenceLoadInputModeType rlm, int &nite, TimeStep *)
Solves the given sparse linear system of equations .
std::vector< FloatArray > X
Abstract class Dof represents Degree Of Freedom in finite element mesh.
Support struct to handle all the split up variables used during the solving step. ...
double localNorm(const FloatArray &src)
Norm for a locally distributed array.
#define OOFEM_WARNING(...)
Class representing solution step.
The staggered solver will perform Newton iterations on subsets of DofIDs, in a staggered manner...
#define _IFT_StaggeredSolver_DofIdListPositions
void add(const FloatArray &src)
Adds array src to receiver.
std::vector< IntArray > locArrayList
void resize(int s)
Resizes receiver towards requested size.