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:
committed by
Knut Morten Okstad
parent
6ab1f0e010
commit
cd4a6e0150
67
Apps/Common/SIMCoupledSI.h
Normal file
67
Apps/Common/SIMCoupledSI.h
Normal 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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user