diff --git a/src/SIM/NonLinSIM.C b/src/SIM/NonLinSIM.C index 3cd017cd..88991a98 100644 --- a/src/SIM/NonLinSIM.C +++ b/src/SIM/NonLinSIM.C @@ -30,7 +30,7 @@ const char* NonLinSIM::inputContext = "nonlinearsolver"; NonLinSIM::NonLinSIM (SIMbase& sim, CNORM n) : MultiStepSIM(sim), iteNorm(n) { // Default solution parameters - fromIni = iteNorm == NONE; + fromIni = iteNorm <= NONE; maxIncr = 2; maxit = 20; nupdat = 20; @@ -131,7 +131,7 @@ bool NonLinSIM::parse (const TiXmlElement* elem) else if (!strcasecmp(value,"max")) refNopt = MAX; } - else if (iteNorm != NONE && (value = utl::getValue(child,"convnorm"))) + else if (iteNorm > NONE && (value = utl::getValue(child,"convnorm"))) { if (!strncasecmp(value,"energ",5)) iteNorm = ENERGY; @@ -151,13 +151,16 @@ bool NonLinSIM::parse (const TiXmlElement* elem) rCond = 0.0; // Compute and report condition number in the iteration log } + if (iteNorm == NONE && nupdat < 0) + iteNorm = NONE_UPTAN; // Recalculate tangent in each step in linear analysis + return true; } void NonLinSIM::initPrm () { - if (iteNorm == NONE) // Flag to integrand that a linear solver is used + if (iteNorm <= NONE) // Flag to integrand that a linear solver is used model.setIntegrationPrm(3,1.0); } @@ -227,7 +230,7 @@ ConvStatus NonLinSIM::solveStep (TimeStep& param, SolutionMode mode, if (!this->assembleSystem(param.time,solution,newTangent)) return model.getProblem()->diverged() ? DIVERGED : FAILURE; - if (iteNorm != NONE) + if (iteNorm > NONE) if (!model.extractLoadVec(residual)) return FAILURE; @@ -391,7 +394,7 @@ bool NonLinSIM::lineSearch (TimeStep& param) ConvStatus NonLinSIM::checkConvergence (TimeStep& param) { - if (iteNorm == NONE) + if (iteNorm <= NONE) return CONVERGED; // No iterations, we are solving a linear problem static double convTol = 0.0; @@ -504,7 +507,7 @@ void NonLinSIM::printWorst (utl::LogStream& os, double eps) bool NonLinSIM::updateConfiguration (TimeStep& time) { - if (solution.front().empty() || iteNorm == NONE) + if (solution.front().empty() || iteNorm <= NONE) { solution.front() = linsol; model.updateRotations(linsol); diff --git a/src/SIM/NonLinSIM.h b/src/SIM/NonLinSIM.h index be36a51f..97ffdf5c 100644 --- a/src/SIM/NonLinSIM.h +++ b/src/SIM/NonLinSIM.h @@ -28,7 +28,13 @@ class NonLinSIM : public MultiStepSIM { public: //! \brief Enum describing the norm used for convergence checks. - enum CNORM { NONE, L2, L2SOL, ENERGY }; + //! \details The value \a NONE imples no checking at all and is used to + //! conduct a pure linear analysis without equilibrium iterations. + //! The value \a NONE_UPTAN value implies the same as \a NONE, but with + //! recalculation of the tangent matrix at each step. This is needed for + //! problems with inhomogeneous dirichlet conditions where the element + //! tangent matrix is used to calculate the equivalent load vector. + enum CNORM { NONE_UPTAN=-1, NONE=0, L2=1, L2SOL=2, ENERGY=3 }; //! \brief The constructor initializes default solution parameters. //! \param sim Pointer to the spline FE model @@ -38,7 +44,7 @@ public: virtual ~NonLinSIM(); //! \brief Defines which type of iteration norm to use in convergence checks. - void setConvNorm(CNORM n) { if ((iteNorm = n) == NONE) fromIni = true; } + void setConvNorm(CNORM n) { if ((iteNorm = n) <= NONE) fromIni = true; } //! \brief Initializes the primary solution vectors. //! \param[in] nSol Number of consequtive solutions stored in core @@ -77,7 +83,7 @@ public: int getMaxit() const { return maxit; } //! \brief Returns whether this solution driver is linear or not. - virtual bool isLinear() const { return iteNorm == NONE; } + virtual bool isLinear() const { return iteNorm <= NONE; } protected: //! \brief Prints out the worst DOFs when slow convergence is detected.