forked from lijiext/lammps
154 lines
5.5 KiB
C++
154 lines
5.5 KiB
C++
#include "FieldEulerIntegrator.h"
|
|
#include "ATC_Coupling.h"
|
|
#include "FE_Engine.h"
|
|
#include "PhysicsModel.h"
|
|
#include "PrescribedDataManager.h"
|
|
//#include "GMRES.h"
|
|
//#include "CG.h"
|
|
#include "ImplicitSolveOperator.h"
|
|
#include "MatrixDef.h"
|
|
#include "LinearSolver.h"
|
|
|
|
namespace ATC {
|
|
|
|
// ====================================================================
|
|
// FieldEulerIntegrator
|
|
// ====================================================================
|
|
FieldEulerIntegrator::FieldEulerIntegrator(
|
|
const FieldName fieldName,
|
|
const PhysicsModel * physicsModel,
|
|
/*const*/ FE_Engine * feEngine,
|
|
/*const*/ ATC_Coupling * atc,
|
|
const Array2D< bool > & rhsMask // copy
|
|
)
|
|
: atc_(atc),
|
|
feEngine_(feEngine),
|
|
physicsModel_(physicsModel),
|
|
fieldName_(fieldName),
|
|
rhsMask_(rhsMask)
|
|
{
|
|
nNodes_ = feEngine->num_nodes();
|
|
}
|
|
|
|
// ====================================================================
|
|
// FieldImplicitIntegrator
|
|
// ====================================================================
|
|
FieldExplicitEulerIntegrator::FieldExplicitEulerIntegrator(
|
|
const FieldName fieldName,
|
|
const PhysicsModel * physicsModel,
|
|
/*const*/ FE_Engine * feEngine,
|
|
/*const*/ ATC_Coupling * atc,
|
|
const Array2D< bool > & rhsMask // copy
|
|
) : FieldEulerIntegrator(fieldName,physicsModel,feEngine,atc,rhsMask)
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// update
|
|
// --------------------------------------------------------------------
|
|
void FieldExplicitEulerIntegrator::update(const double dt, double time,
|
|
FIELDS & fields, FIELDS & rhs)
|
|
{
|
|
// write and add update mass matrix to handled time variation
|
|
// update mass matrix to be consistent/lumped, and handle this in apply_inverse_mass_matrix
|
|
atc_->compute_rhs_vector(rhsMask_, fields, rhs,
|
|
FULL_DOMAIN, physicsModel_);
|
|
DENS_MAT & myRhs(rhs[fieldName_].set_quantity());
|
|
atc_->apply_inverse_mass_matrix(myRhs,fieldName_);
|
|
fields[fieldName_] += dt*myRhs;
|
|
}
|
|
|
|
// ====================================================================
|
|
// FieldImplicitEulerIntegrator
|
|
// ====================================================================
|
|
FieldImplicitEulerIntegrator::FieldImplicitEulerIntegrator(
|
|
const FieldName fieldName,
|
|
const PhysicsModel * physicsModel,
|
|
/*const*/ FE_Engine * feEngine,
|
|
/*const*/ ATC_Coupling * atc,
|
|
const Array2D< bool > & rhsMask, // copy
|
|
const double alpha
|
|
) : FieldEulerIntegrator(fieldName,physicsModel,feEngine,atc,rhsMask),
|
|
alpha_(alpha),
|
|
dT_(1.0e-6),
|
|
maxRestarts_(50),
|
|
maxIterations_(1000),
|
|
tol_(1.0e-8)
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// update
|
|
// --------------------------------------------------------------------
|
|
void FieldImplicitEulerIntegrator::update(const double dt, double time,
|
|
FIELDS & fields, FIELDS & rhs)
|
|
{ // solver handles bcs
|
|
FieldImplicitSolveOperator solver(atc_,
|
|
fields, fieldName_, rhsMask_, physicsModel_,
|
|
time, dt, alpha_);
|
|
DiagonalMatrix<double> preconditioner = solver.preconditioner();
|
|
DENS_VEC rT = solver.r();
|
|
DENS_VEC dT(nNodes_); dT = dT_;
|
|
DENS_MAT H(maxRestarts_+1, maxRestarts_);
|
|
double tol = tol_; // tol returns the residual
|
|
int iterations = maxIterations_; // iterations returns number of iterations
|
|
int restarts = maxRestarts_;
|
|
int convergence = GMRES(solver,
|
|
dT, rT, preconditioner, H, restarts, iterations, tol);
|
|
if (convergence != 0) {
|
|
throw ATC_Error(field_to_string(fieldName_) + " evolution did not converge");
|
|
}
|
|
solver.solution(dT,fields[fieldName_].set_quantity());
|
|
}
|
|
|
|
// ====================================================================
|
|
// FieldImplicitDirectEulerIntegrator
|
|
// ====================================================================
|
|
FieldImplicitDirectEulerIntegrator::FieldImplicitDirectEulerIntegrator(
|
|
const FieldName fieldName,
|
|
const PhysicsModel * physicsModel,
|
|
/*const*/ FE_Engine * feEngine,
|
|
/*const*/ ATC_Coupling * atc,
|
|
const Array2D< bool > & rhsMask, // copy
|
|
const double alpha
|
|
) : FieldEulerIntegrator(fieldName,physicsModel,feEngine,atc,rhsMask),
|
|
alpha_(alpha),solver_(NULL)
|
|
{
|
|
rhsMask_(fieldName_,FLUX) = false; // handle laplacian term with stiffness
|
|
const BC_SET & bcs = (atc_->prescribed_data_manager()->bcs(fieldName_))[0];
|
|
solver_ = new LinearSolver(_lhsMK_,bcs);
|
|
solver_->allow_reinitialization();
|
|
}
|
|
FieldImplicitDirectEulerIntegrator::~FieldImplicitDirectEulerIntegrator()
|
|
{
|
|
if (solver_) delete solver_;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// initialize
|
|
// --------------------------------------------------------------------
|
|
void FieldImplicitDirectEulerIntegrator::initialize(const double dt, double time,
|
|
FIELDS & fields)
|
|
{
|
|
std::pair<FieldName,FieldName> p(fieldName_,fieldName_);
|
|
Array2D <bool> rmask = atc_->rhs_mask();
|
|
rmask(fieldName_,FLUX) = true;
|
|
atc_->tangent_matrix(p,rmask,physicsModel_,_K_);
|
|
_lhsMK_ = (1./dt)*(_M_)- alpha_*(_K_);
|
|
_rhsMK_ = (1./dt)*(_M_)+(1.+alpha_)*(_K_);
|
|
}
|
|
// --------------------------------------------------------------------
|
|
// update
|
|
// --------------------------------------------------------------------
|
|
void FieldImplicitDirectEulerIntegrator::update(const double dt, double time,
|
|
FIELDS & fields, FIELDS & rhs)
|
|
{
|
|
atc_->compute_rhs_vector(rhsMask_, fields, rhs,
|
|
FULL_DOMAIN, physicsModel_);
|
|
CLON_VEC myRhs = column( rhs[fieldName_].set_quantity(),0);
|
|
CLON_VEC myField = column(fields[fieldName_].set_quantity(),0);
|
|
myRhs += _rhsMK_*myField; // f = (1/dt M + (1+alpha) K) T + f
|
|
solver_->solve(myField,myRhs); // (1/dt M -alpha K)^-1 f
|
|
}
|
|
} // namespace ATC
|