Renamed SIMCoupledSemiImplicit.h to SIMCoupledSI.h

Also rewrite the template to use the convergence tests of the
nonlinear/newmark solvers instead of adding another on top.
This commit is contained in:
Arne Morten Kvarving
2016-01-15 10:57:47 +01:00
committed by Knut Morten Okstad
parent 6ab1f0e010
commit cd4a6e0150
6 changed files with 134 additions and 131 deletions

View File

@@ -0,0 +1,67 @@
// $Id$
//==============================================================================
//!
//! \file SIMCoupledSI.h
//!
//! \date Mar 19 2014
//!
//! \author Arne Morten Kvarving / SINTEF
//!
//! \brief Template for a semi-implicit coupling of two nonlinear solvers.
//!
//==============================================================================
#ifndef SIM_COUPLED_SI_H_
#define SIM_COUPLED_SI_H_
#include "SIMCoupled.h"
/*!
\brief Template class for semi-implicitly coupled simulators.
*/
template<class T1, class T2>
class SIMCoupledSI : public SIMCoupled<T1, T2>
{
public:
//! \brief The constructor initializes the references to the two solvers.
SIMCoupledSI(T1& t1_, T2& t2_) : SIMCoupled<T1,T2>(t1_,t2_) {}
//! \brief Empty destructor.
virtual ~SIMCoupledSI() {}
//! \brief Computes the solution for the current time step.
bool solveStep(TimeStep& tp)
{
int maxit = std::min(this->S1.getMaxit(),this->S2.getMaxit());
this->S1.updateDirichlet(tp.time.t,&this->S1.getSolution(0));
this->S2.updateDirichlet(tp.time.t,&this->S2.getSolution(0));
this->S1.getProcessAdm().cout <<"\n step="<< tp.step
<<" time="<< tp.time.t << std::endl;
SIM::ConvStatus status1 = SIM::OK, status2 = SIM::OK;
for (tp.iter = 0; tp.iter < maxit; tp.iter++)
{
if ((status1 = this->S1.solveIteration(tp)) == SIM::DIVERGED)
return false;
if ((status2 = this->S2.solveIteration(tp)) == SIM::DIVERGED)
return false;
if (status1 == SIM::CONVERGED && status2 == SIM::CONVERGED)
break; // Exit iteration loop when both solvers have converged
this->S1.updateDirichlet();
this->S2.updateDirichlet();
}
tp.time.first = false;
this->S1.postSolve(tp);
this->S2.postSolve(tp);
return true;
}
};
#endif

View File

@@ -1,102 +0,0 @@
// $Id$
//==============================================================================
//!
//! \file SIMCoupledSemiImplicit.h
//!
//! \date Mar 19 2014
//!
//! \author Arne Morten Kvarving / SINTEF
//!
//! \brief Template for a semi-implicit coupling of two solvers
//!
//==============================================================================
#ifndef SIM_COUPLED_SEMIIMPLICIT_H_
#define SIM_COUPLED_SEMIIMPLICIT_H_
#include "SIMCoupled.h"
/*!
\brief Template class for semi-implicitly coupled simulators.
*/
template<class T1, class T2>
class SIMCoupledSemiImplicit : public SIMCoupled<T1, T2> {
public:
//! \brief The constructor initializes the references to the two solvers.
SIMCoupledSemiImplicit(T1& t1_, T2& t2_) :
SIMCoupled<T1,T2>(t1_, t2_)
{
}
//! \brief Empty destructor.
virtual ~SIMCoupledSemiImplicit() {}
//! \brief Computes the solution for the current time step.
bool solveStep(TimeStep& tp)
{
double rtol, atol, dtol;
int its1, its2;
this->S2.getTolerances(atol, rtol, dtol, its2);
this->S1.getTolerances(atol, rtol, dtol, its1);
double r1=rtol+1.0, r2=rtol+1.0, r1r=1.0, r2r=1.0;
this->S1.updateDirichlet(tp.time.t,&this->S1.getSolution(0));
this->S2.updateDirichlet(tp.time.t,&this->S2.getSolution(0));
int old1 = this->S1.msgLevel;
this->S1.msgLevel = 0;
if (this->S1.getGlobalProcessID() == 0)
std::cout <<"\n step="<< tp.step <<" time="<< tp.time.t << std::endl;
int it=0;
bool abs1=true, abs2 = true, rel1=true, rel2=true;
while (true) {
++it;
for (int i=0;i<its1;++i && r1 > atol) {
if (!this->S1.solveLinearizedSystem(tp,r1))
return false;
this->S1.updateDirichlet();
if (it == 1 && i == 0)
r1r = r1>0.0?r1:1.0;
}
for (int i=0;i<its2;++i && r2 > atol) {
if (!this->S2.solveLinearizedSystem(tp,r2))
return false;
this->S2.updateDirichlet();
if (it == 1 && i == 0)
r2r = r2>0.0?r2:1.0;
}
if (r1 < atol)
abs1 = false;
if (r2 < atol)
abs2 = false;
if (r1/r1r < rtol)
rel1 = false;
if (r2/r2r < rtol)
rel2 = false;
if (r1/r1r > dtol || r2/r2r > dtol)
return false;
if (this->S1.getGlobalProcessID() == 0) {
std::streamsize oldPrec = std::cout.precision(3);
std::ios::fmtflags oldFlags = std::cout.flags(std::ios::scientific);
std::cout << " iter=" << it << " " << this->S1.getName() << ": conv=" << r1/r1r << " incn=" << r1 << " " << this->S2.getName() << ": conv=" << r2/r2r << " incn=" << r2 << std::endl;
std::cout.precision(oldPrec);
std::cout.flags(oldFlags);
}
if ((!abs1 || !rel1) && (!abs2 || !rel2))
break;
}
this->S1.msgLevel = old1;
this->S1.printSolutionSummary(this->S1.getSolution(0),0,nullptr,6);
this->S2.printSolutionSummary(this->S2.getSolution(0),0,nullptr,6);
return true;
}
};
#endif

View File

@@ -382,6 +382,39 @@ SIM::ConvStatus NewmarkSIM::solveStep (TimeStep& param, SIM::SolutionMode,
}
SIM::ConvStatus NewmarkSIM::solveIteration (TimeStep& param)
{
bool ok = false;
if (param.iter > 0)
ok = this->correctStep(param);
else
ok = this->predictStep(param);
if (!ok)
return SIM::FAILURE;
if (!model.setMode(SIM::DYNAMIC))
return SIM::FAILURE;
if (!model.assembleSystem(param.time,solution))
return SIM::FAILURE;
this->finalizeRHSvector(!param.time.first && param.iter == 0);
if (!model.extractLoadVec(residual))
return SIM::FAILURE;
if (!model.solveSystem(linsol,msgLevel-1))
return SIM::FAILURE;
SIM::ConvStatus result = checkConvergence(param);
if (result == SIM::CONVERGED)
if (!this->solutionNorms(param.time))
return SIM::FAILURE;
return result;
}
SIM::ConvStatus NewmarkSIM::checkConvergence (TimeStep& param)
{
static double prevNorm = 0.0;

View File

@@ -51,6 +51,13 @@ public:
double zero_tolerance = 1.0e-8,
std::streamsize outPrec = 0);
//! \brief Solves the linearized system of current iteration.
//! \param[in] param Time stepping parameters
SIM::ConvStatus solveIteration(TimeStep& param);
//! \brief Returns the maximum number of iterations.
int getMaxit() const { return maxit; }
protected:
//! \brief Computes and prints some solution norm quantities.
//! \param[in] zero_tolerance Truncate norm values smaller than this to zero

View File

@@ -144,16 +144,6 @@ bool NonLinSIM::parse (const TiXmlElement* elem)
}
void NonLinSIM::getTolerances (double& atol, double& rtol,
double& dtol, int& mxit) const
{
atol = aTol;
rtol = rTol;
dtol = divgLim;
mxit = maxit;
}
void NonLinSIM::init (size_t nSol, const RealArray& value)
{
this->MultiStepSIM::initSol(nSol);
@@ -290,19 +280,32 @@ ConvStatus NonLinSIM::solveStep (TimeStep& param, SolutionMode mode,
}
bool NonLinSIM::solveLinearizedSystem (const TimeStep& param, double& norm)
SIM::ConvStatus NonLinSIM::solveIteration (TimeStep& param)
{
if (!model.setMode(SIM::DYNAMIC))
return SIM::FAILURE;
if (!model.assembleSystem(param.time,solution))
return false;
return SIM::FAILURE;
Vector inc;
model.extractLoadVec(inc);
norm = model.solutionNorms(inc);
if (!model.solveSystem(inc))
return false;
if (!model.extractLoadVec(residual))
return SIM::FAILURE;
solution.front().add(inc);
return true;
if (!model.solveSystem(linsol,msgLevel-1))
return SIM::FAILURE;
if (!this->lineSearch(param))
return SIM::FAILURE;
if (!this->updateConfiguration(param))
return SIM::FAILURE;
SIM::ConvStatus result = checkConvergence(param);
if (result == SIM::CONVERGED)
if (!this->solutionNorms(param.time))
return SIM::FAILURE;
return result;
}

View File

@@ -40,13 +40,6 @@ public:
//! \brief Defines which type of iteration norm to use in convergence checks.
void setConvNorm(CNORM n) { if ((iteNorm = n) == NONE) fromIni = true; }
//! \brief Returns solver configuration parameters.
//! \param[out] atol Absolute residual norm tolerance
//! \param[out] rtol Relative residual norm tolerance
//! \param[out] dtol Relative divergence limit
//! \param[out] mxit Maximum number of iterations
void getTolerances(double& atol, double& rtol, double& dtol, int& mxit) const;
//! \brief Initializes the primary solution vectors.
//! \param[in] nSol Number of consequtive solutions stored in core
//! \param[in] initVal Initial values of the primary solution
@@ -73,10 +66,12 @@ public:
double zero_tolerance = 1.0e-8,
std::streamsize outPrec = 0);
//! \brief Solves the current linearized system.
//! \brief Solves the linearized system of current iteration.
//! \param[in] param Time stepping parameters
//! \param[out] norm The norm of the residual
bool solveLinearizedSystem(const TimeStep& param, double& norm);
SIM::ConvStatus solveIteration(TimeStep& param);
//! \brief Returns the maximum number of iterations.
int getMaxit() const { return maxit; }
protected:
//! \brief Checks whether the nonlinear iterations have converged or diverged.