forked from lijiext/lammps
704 lines
28 KiB
C++
704 lines
28 KiB
C++
#include "KinetoThermostat.h"
|
|
#include "ATC_Coupling.h"
|
|
#include "ATC_Error.h"
|
|
#include "PrescribedDataManager.h"
|
|
#include "ElasticTimeIntegrator.h"
|
|
#include "ThermalTimeIntegrator.h"
|
|
#include "TransferOperator.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace ATC {
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class KinetoThermostat
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
KinetoThermostat::KinetoThermostat(ATC_Coupling * atc,
|
|
const string & regulatorPrefix) :
|
|
AtomicRegulator(atc,regulatorPrefix),
|
|
couplingMaxIterations_(myCouplingMaxIterations)
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// modify:
|
|
// parses and adjusts thermostat state based on
|
|
// user input, in the style of LAMMPS user input
|
|
//--------------------------------------------------------
|
|
bool KinetoThermostat::modify(int narg, char **arg)
|
|
{
|
|
bool foundMatch = false;
|
|
return foundMatch;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// reset_lambda_contribution:
|
|
// resets the thermostat generated power to a
|
|
// prescribed value
|
|
//--------------------------------------------------------
|
|
void KinetoThermostat::reset_lambda_contribution(const DENS_MAT & target,
|
|
const FieldName field)
|
|
{
|
|
if (field==VELOCITY) {
|
|
DENS_MAN * lambdaForceFiltered = regulator_data("LambdaForceFiltered",atc_->nsd());
|
|
*lambdaForceFiltered = target;
|
|
}
|
|
else if (field == TEMPERATURE) {
|
|
DENS_MAN * lambdaPowerFiltered = regulator_data("LambdaPowerFiltered",1);
|
|
*lambdaPowerFiltered = target;
|
|
}
|
|
else {
|
|
throw ATC_Error("KinetoThermostat::reset_lambda_contribution - invalid field given");
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// construct_methods:
|
|
// instantiations desired regulator method(s)
|
|
|
|
// dependence, but in general there is also a
|
|
// time integrator dependence. In general the
|
|
// precedence order is:
|
|
// time filter -> time integrator -> thermostat
|
|
// In the future this may need to be added if
|
|
// different types of time integrators can be
|
|
// specified.
|
|
//--------------------------------------------------------
|
|
void KinetoThermostat::construct_methods()
|
|
{
|
|
// get data associated with stages 1 & 2 of ATC_Method::initialize
|
|
AtomicRegulator::construct_methods();
|
|
|
|
if (atc_->reset_methods()) {
|
|
// eliminate existing methods
|
|
delete_method();
|
|
|
|
// error check time integration methods
|
|
TimeIntegrator::TimeIntegrationType myEnergyIntegrationType = (atc_->time_integrator(TEMPERATURE))->time_integration_type();
|
|
TimeIntegrator::TimeIntegrationType myMomentumIntegrationType = (atc_->time_integrator(VELOCITY))->time_integration_type();
|
|
if (myEnergyIntegrationType != TimeIntegrator::FRACTIONAL_STEP || myMomentumIntegrationType != TimeIntegrator::FRACTIONAL_STEP) {
|
|
throw ATC_Error("KinetoThermostat::construct_methods - this scheme only valid with fractional step integration");
|
|
}
|
|
|
|
// update time filter
|
|
TimeFilterManager * timeFilterManager = atc_->time_filter_manager();
|
|
if (timeFilterManager->need_reset() ) {
|
|
timeFilter_ = timeFilterManager->construct(TimeFilterManager::EXPLICIT_IMPLICIT);
|
|
}
|
|
|
|
if (timeFilterManager->filter_dynamics()) {
|
|
switch (regulatorTarget_) {
|
|
case NONE: {
|
|
regulatorMethod_ = new RegulatorMethod(this);
|
|
break;
|
|
}
|
|
case FIELD: { // error check, rescale and filtering not supported together
|
|
throw ATC_Error("KinetoThermostat::construct_methods - Cannot use rescaling thermostat with time filtering");
|
|
break;
|
|
}
|
|
case DYNAMICS: {
|
|
}
|
|
default:
|
|
throw ATC_Error("Unknown thermostat type in Thermostat::initialize");
|
|
}
|
|
}
|
|
else {
|
|
switch (regulatorTarget_) {
|
|
case NONE: {
|
|
regulatorMethod_ = new RegulatorMethod(this);
|
|
break;
|
|
}
|
|
case FIELD: {
|
|
if (atc_->temperature_def()==KINETIC) {
|
|
regulatorMethod_ = new KinetoThermostatRescale(this,couplingMaxIterations_);
|
|
}
|
|
else if (atc_->temperature_def()==TOTAL) {
|
|
regulatorMethod_ = new KinetoThermostatRescaleMixedKePe(this,couplingMaxIterations_);
|
|
}
|
|
else
|
|
throw ATC_Error("Unknown temperature definition");
|
|
break;
|
|
}
|
|
default:
|
|
throw ATC_Error("Unknown thermostat target in Thermostat::initialize");
|
|
}
|
|
}
|
|
|
|
AtomicRegulator::reset_method();
|
|
}
|
|
else {
|
|
set_all_data_to_used();
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class VelocityRescaleCombined
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
// Grab references to ATC and kinetostat data
|
|
//--------------------------------------------------------
|
|
VelocityRescaleCombined::VelocityRescaleCombined(AtomicRegulator * kinetostat) :
|
|
VelocityGlc(kinetostat),
|
|
velocity_(atc_->field(VELOCITY)),
|
|
thermostatCorrection_(NULL)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// initialize
|
|
// initializes all data
|
|
//--------------------------------------------------------
|
|
void VelocityRescaleCombined::initialize()
|
|
{
|
|
VelocityGlc::initialize();
|
|
thermostatCorrection_ = (atc_->interscale_manager()).dense_matrix("NodalAtomicFluctuatingMomentumRescaled");
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// set_kinetostat_rhs
|
|
// sets up the right-hand side of the
|
|
// kinetostat equations
|
|
//--------------------------------------------------------
|
|
void VelocityRescaleCombined::set_kinetostat_rhs(DENS_MAT & rhs, double dt)
|
|
{
|
|
rhs = ((atc_->mass_mat_md(VELOCITY)).quantity())*(velocity_.quantity());
|
|
rhs -= thermostatCorrection_->quantity();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class ThermostatRescaleCombined
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
ThermostatRescaleCombined::ThermostatRescaleCombined(AtomicRegulator * thermostat) :
|
|
ThermostatRescale(thermostat),
|
|
kinetostatCorrection_(NULL)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// initialize
|
|
// initializes all data
|
|
//--------------------------------------------------------
|
|
void ThermostatRescaleCombined::initialize()
|
|
{
|
|
ThermostatRescale::initialize();
|
|
kinetostatCorrection_ = (atc_->interscale_manager()).dense_matrix("NodalAtomicCombinedRescaleThermostatError");
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// set_rhs:
|
|
// constructs the RHS vector with the target
|
|
// temperature
|
|
//--------------------------------------------------------
|
|
void ThermostatRescaleCombined::set_rhs(DENS_MAT & rhs)
|
|
{
|
|
ThermostatRescale::set_rhs(rhs);
|
|
rhs -= kinetostatCorrection_->quantity();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class KinetoThermostatRescale
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
KinetoThermostatRescale::KinetoThermostatRescale(AtomicRegulator * kinetoThermostat,
|
|
int couplingMaxIterations) :
|
|
KinetoThermostatShapeFunction(kinetoThermostat,couplingMaxIterations),
|
|
atomVelocities_(NULL),
|
|
nodalVelocities_(atc_->field(VELOCITY)),
|
|
lambdaMomentum_(NULL),
|
|
lambdaEnergy_(NULL),
|
|
atomicFluctuatingVelocityRescaled_(NULL),
|
|
atomicStreamingVelocity_(NULL),
|
|
thermostat_(NULL),
|
|
kinetostat_(NULL)
|
|
{
|
|
thermostat_ = this->construct_rescale_thermostat();
|
|
kinetostat_ = new VelocityRescaleCombined(kinetoThermostat);
|
|
// data associated with stage 3 in ATC_Method::initialize
|
|
lambdaMomentum_ = atomicRegulator_->regulator_data(regulatorPrefix_+"LambdaMomentum",atc_->nsd());
|
|
lambdaEnergy_ = atomicRegulator_->regulator_data(regulatorPrefix_+"LambdaEnergy",1);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// Destructor
|
|
//--------------------------------------------------------
|
|
KinetoThermostatRescale::~KinetoThermostatRescale()
|
|
{
|
|
if (thermostat_) delete thermostat_;
|
|
if (kinetostat_) delete kinetostat_;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// constructor_transfers
|
|
// instantiates or obtains all dependency managed data
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatRescale::construct_transfers()
|
|
{
|
|
// construct independent transfers first
|
|
thermostat_->construct_transfers();
|
|
kinetostat_->construct_transfers();
|
|
|
|
InterscaleManager & interscaleManager(atc_->interscale_manager());
|
|
|
|
// get atom velocity data from manager
|
|
atomVelocities_ = interscaleManager.fundamental_atom_quantity(LammpsInterface::ATOM_VELOCITY);
|
|
|
|
// transfers requiring terms from both regulators
|
|
// rescaled velocity fluctuations
|
|
atomicFluctuatingVelocityRescaled_ = new AtomicFluctuatingVelocityRescaled(atc_);
|
|
interscaleManager.add_per_atom_quantity(atomicFluctuatingVelocityRescaled_,
|
|
"AtomFluctuatingVelocityRescaled");
|
|
|
|
// streaming velocity component
|
|
atomicStreamingVelocity_ = interscaleManager.per_atom_quantity("AtomLambdaMomentum");
|
|
|
|
// rescaled momentum fluctuations, error term for kinetostat rhs
|
|
PerAtomQuantity<double> * tempAtom = new AtomicMomentum(atc_,
|
|
atomicFluctuatingVelocityRescaled_);
|
|
interscaleManager.add_per_atom_quantity(tempAtom,"AtomFluctuatingMomentumRescaled");
|
|
DENS_MAN * tempNodes = new AtfShapeFunctionRestriction(atc_,
|
|
tempAtom,
|
|
interscaleManager.per_atom_sparse_matrix("Interpolant"));
|
|
interscaleManager.add_dense_matrix(tempNodes,
|
|
"NodalAtomicFluctuatingMomentumRescaled");
|
|
|
|
// error term for thermostat rhs
|
|
tempAtom = new AtomicCombinedRescaleThermostatError(atc_);
|
|
interscaleManager.add_per_atom_quantity(tempAtom,"AtomCombinedRescaleThermostatError");
|
|
tempNodes = new AtfShapeFunctionRestriction(atc_,
|
|
tempAtom,
|
|
interscaleManager.per_atom_sparse_matrix("Interpolant"));
|
|
interscaleManager.add_dense_matrix(tempNodes,
|
|
"NodalAtomicCombinedRescaleThermostatError");
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// construct_rescale_thermostat
|
|
// constructs the appropriate rescaling thermostat
|
|
// varied through inheritance
|
|
//--------------------------------------------------------
|
|
ThermostatRescale * KinetoThermostatRescale::construct_rescale_thermostat()
|
|
{
|
|
return new ThermostatRescaleCombined(atomicRegulator_);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// initialize
|
|
// initializes all data
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatRescale::initialize()
|
|
{
|
|
KinetoThermostatShapeFunction::initialize();
|
|
thermostat_->initialize();
|
|
kinetostat_->initialize();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// apply_post_corrector:
|
|
// apply the thermostat in the post corrector phase
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatRescale::apply_post_corrector(double dt)
|
|
{
|
|
// initial guesses
|
|
lambdaMomentum_->set_quantity() = nodalVelocities_.quantity();
|
|
lambdaEnergy_->set_quantity() = 1.;
|
|
|
|
int iteration = 0;
|
|
double eErr, pErr;
|
|
while (iteration < couplingMaxIterations_) {
|
|
_lambdaMomentumOld_ = lambdaMomentum_->quantity();
|
|
_lambdaEnergyOld_ = lambdaEnergy_->quantity();
|
|
|
|
// update thermostat
|
|
thermostat_->compute_thermostat(dt);
|
|
|
|
// update kinetostat
|
|
kinetostat_->compute_kinetostat(dt);
|
|
|
|
// check convergence
|
|
_diff_ = lambdaEnergy_->quantity() - _lambdaEnergyOld_;
|
|
eErr = _diff_.col_norm()/_lambdaEnergyOld_.col_norm();
|
|
_diff_ = lambdaMomentum_->quantity() - _lambdaMomentumOld_;
|
|
pErr = _diff_.col_norm()/_lambdaMomentumOld_.col_norm();
|
|
if (eErr < tolerance_ && pErr < tolerance_) {
|
|
break;
|
|
}
|
|
iteration++;
|
|
}
|
|
if (iteration == couplingMaxIterations_) {
|
|
stringstream message;
|
|
message << "WARNING: Iterative solve for lambda failed to converge after " << couplingMaxIterations_ << " iterations, final tolerance was " << std::max(eErr,pErr) << "\n";
|
|
ATC::LammpsInterface::instance()->print_msg(message.str());
|
|
}
|
|
|
|
// application of rescaling lambda due
|
|
apply_to_atoms(atomVelocities_);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// apply_lambda_to_atoms:
|
|
// applies the velocity rescale with an existing lambda
|
|
// note oldAtomicQuantity and dt are not used
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatRescale::apply_to_atoms(PerAtomQuantity<double> * atomVelocities)
|
|
{
|
|
*atomVelocities = atomicFluctuatingVelocityRescaled_->quantity() + atomicStreamingVelocity_->quantity();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// output:
|
|
// adds all relevant output to outputData
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatRescale::output(OUTPUT_LIST & outputData)
|
|
{
|
|
thermostat_->output(outputData);
|
|
kinetostat_->output(outputData);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class ThermostatRescaleMixedKePeCombined
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
ThermostatRescaleMixedKePeCombined::ThermostatRescaleMixedKePeCombined(AtomicRegulator * thermostat) :
|
|
ThermostatRescaleMixedKePe(thermostat),
|
|
kinetostatCorrection_(NULL)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// initialize
|
|
// initializes all data
|
|
//--------------------------------------------------------
|
|
void ThermostatRescaleMixedKePeCombined::initialize()
|
|
{
|
|
ThermostatRescaleMixedKePe::initialize();
|
|
kinetostatCorrection_ = (atc_->interscale_manager()).dense_matrix("NodalAtomicCombinedRescaleThermostatError");
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// set_rhs:
|
|
// constructs the RHS vector with the target
|
|
// temperature
|
|
//--------------------------------------------------------
|
|
void ThermostatRescaleMixedKePeCombined::set_rhs(DENS_MAT & rhs)
|
|
{
|
|
ThermostatRescaleMixedKePe::set_rhs(rhs);
|
|
rhs -= kinetostatCorrection_->quantity();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class KinetoThermostatRescaleMixedKePe
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
KinetoThermostatRescaleMixedKePe::KinetoThermostatRescaleMixedKePe(AtomicRegulator * kinetoThermostat,
|
|
int couplingMaxIterations) :
|
|
KinetoThermostatRescale(kinetoThermostat,couplingMaxIterations)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// construct_rescale_thermostat
|
|
// constructs the appropriate rescaling thermostat
|
|
// varied through inheritance
|
|
//--------------------------------------------------------
|
|
ThermostatRescale * KinetoThermostatRescaleMixedKePe::construct_rescale_thermostat()
|
|
{
|
|
return new ThermostatRescaleMixedKePeCombined(atomicRegulator_);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
// Class KinetoThermostatGlcFs
|
|
//--------------------------------------------------------
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
// Constructor
|
|
//--------------------------------------------------------
|
|
KinetoThermostatGlcFs::KinetoThermostatGlcFs(AtomicRegulator * kinetoThermostat,
|
|
int couplingMaxIterations,
|
|
const string & regulatorPrefix) :
|
|
KinetoThermostatShapeFunction(kinetoThermostat,couplingMaxIterations,regulatorPrefix),
|
|
velocity_(atc_->field(VELOCITY)),
|
|
temperature_(atc_->field(TEMPERATURE)),
|
|
timeFilter_(atomicRegulator_->time_filter()),
|
|
nodalAtomicLambdaForce_(NULL),
|
|
lambdaForceFiltered_(NULL),
|
|
nodalAtomicLambdaPower_(NULL),
|
|
lambdaPowerFiltered_(NULL),
|
|
atomRegulatorForces_(NULL),
|
|
atomThermostatForces_(NULL),
|
|
atomMasses_(NULL),
|
|
atomVelocities_(NULL),
|
|
isFirstTimestep_(true),
|
|
nodalAtomicMomentum_(NULL),
|
|
nodalAtomicEnergy_(NULL),
|
|
atomPredictedVelocities_(NULL),
|
|
nodalAtomicPredictedMomentum_(NULL),
|
|
nodalAtomicPredictedEnergy_(NULL),
|
|
firstHalfAtomForces_(NULL),
|
|
dtFactor_(0.)
|
|
{
|
|
// construct/obtain data corresponding to stage 3 of ATC_Method::initialize
|
|
//nodalAtomicLambdaPower_ = thermostat->regulator_data(regulatorPrefix_+"NodalAtomicLambdaPower",1);
|
|
//lambdaPowerFiltered_ = thermostat_->regulator_data(regulatorPrefix_+"LambdaPowerFiltered",1);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// constructor_transfers
|
|
// instantiates or obtains all dependency managed data
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::construct_transfers()
|
|
{
|
|
// BASES INITIALIZE
|
|
// GRAB ANY COPIES FROM BASES
|
|
|
|
// TOTAL REGULATOR FORCE
|
|
// TOTAL FIRST HALF FORCE, IF NECESSARY
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// initialize
|
|
// initializes all method data
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::initialize()
|
|
{
|
|
RegulatorMethod::initialize();
|
|
|
|
// INITIALIZE BASES
|
|
|
|
// MAKE SURE ANY NEEDED POINTERS FROM BASES ARE COPIED BY HERE
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// apply_to_atoms:
|
|
// determines what if any contributions to the
|
|
// atomic moition is needed for
|
|
// consistency with the thermostat
|
|
// and computes the instantaneous induced power
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::apply_to_atoms(PerAtomQuantity<double> * atomicVelocity,
|
|
const DENS_MAN * nodalAtomicMomentum,
|
|
const DENS_MAN * nodalAtomicEnergy,
|
|
const DENS_MAT & lambdaForce,
|
|
DENS_MAT & nodalAtomicLambdaForce,
|
|
DENS_MAT & nodalAtomicLambdaPower,
|
|
double dt)
|
|
{
|
|
// compute initial contributions to lambda force and power
|
|
nodalAtomicLambdaPower = nodalAtomicEnergy->quantity();
|
|
nodalAtomicLambdaPower *= -1.;
|
|
nodalAtomicLambdaForce = nodalAtomicMomentum->quantity();
|
|
nodalAtomicLambdaForce *= -1.;
|
|
|
|
// apply lambda force to atoms
|
|
_velocityDelta_ = lambdaForce;
|
|
_velocityDelta_ /= atomMasses_->quantity();
|
|
_velocityDelta_ *= dt;
|
|
(*atomicVelocity) += _velocityDelta_;
|
|
|
|
// finalize lambda force and power
|
|
nodalAtomicLambdaForce += nodalAtomicMomentum->quantity();
|
|
nodalAtomicLambdaPower += nodalAtomicEnergy->quantity();
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// full_prediction:
|
|
// flag to perform a full prediction calcalation
|
|
// for lambda rather than using the old value
|
|
//--------------------------------------------------------
|
|
bool KinetoThermostatGlcFs::full_prediction()
|
|
{
|
|
// CHECK BOTH BASES
|
|
return false;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// apply_predictor:
|
|
// apply the thermostat to the atoms in the first step
|
|
// of the Verlet algorithm
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::apply_pre_predictor(double dt)
|
|
{
|
|
DENS_MAT & lambdaForceFiltered(lambdaForceFiltered_->set_quantity());
|
|
DENS_MAT & nodalAtomicLambdaForce(nodalAtomicLambdaForce_->set_quantity());
|
|
DENS_MAT & myLambdaPowerFiltered(lambdaPowerFiltered_->set_quantity());
|
|
DENS_MAT & myNodalAtomicLambdaPower(nodalAtomicLambdaPower_->set_quantity());
|
|
|
|
// update filtered forces power, equivalent to measuring changes in momentum and energy
|
|
timeFilter_->apply_pre_step1(lambdaForceFiltered,nodalAtomicLambdaForce,dt);
|
|
timeFilter_->apply_pre_step1(myLambdaPowerFiltered,myNodalAtomicLambdaPower,dt);
|
|
|
|
// apply lambda force to atoms and compute instantaneous lambda power for first half of time step
|
|
this->apply_to_atoms(atomVelocities_,nodalAtomicMomentum_,nodalAtomicEnergy_,
|
|
firstHalfAtomForces_->quantity(),
|
|
nodalAtomicLambdaForce,myNodalAtomicLambdaPower,0.5*dt);
|
|
|
|
// update nodal variables for first half of time step
|
|
// velocity
|
|
this->add_to_momentum(nodalAtomicLambdaForce,deltaMomentum_,0.5*dt);
|
|
atc_->apply_inverse_mass_matrix(deltaMomentum_,VELOCITY);
|
|
velocity_ += deltaMomentum_;
|
|
// temperature
|
|
this->add_to_energy(myNodalAtomicLambdaPower,deltaEnergy1_,0.5*dt);
|
|
|
|
// start update of filtered lambda force and power using temporary (i.e., 0 valued) quantities for first part of update
|
|
nodalAtomicLambdaForce = 0.;
|
|
timeFilter_->apply_post_step1(lambdaForceFiltered,nodalAtomicLambdaForce,dt);
|
|
myNodalAtomicLambdaPower = 0.;
|
|
timeFilter_->apply_post_step1(myLambdaPowerFiltered,myNodalAtomicLambdaPower,dt);
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// apply_pre_corrector:
|
|
// apply the thermostat to the atoms in the first part
|
|
// of the corrector step of the Verlet algorithm
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::apply_pre_corrector(double dt)
|
|
{
|
|
// CHECK WHEN CREATING PREDICTED VELOCITIES IN BASE REGULATORS, ONLY NEED ONE
|
|
(*atomPredictedVelocities_) = atomVelocities_->quantity();
|
|
|
|
// do full prediction if we just redid the shape functions
|
|
if (full_prediction()) {
|
|
this->compute_lambda(dt);
|
|
|
|
atomThermostatForces_->unfix_quantity(); // allow update of atomic force applied by lambda
|
|
}
|
|
|
|
// apply lambda force to atoms and compute instantaneous lambda power to predict second half of time step
|
|
DENS_MAT & myNodalAtomicLambdaForce(nodalAtomicLambdaForce_->set_quantity());
|
|
DENS_MAT & myNodalAtomicLambdaPower(nodalAtomicLambdaPower_->set_quantity());
|
|
apply_to_atoms(atomPredictedVelocities_,
|
|
nodalAtomicPredictedMomentum_,nodalAtomicPredictedEnergy_,
|
|
firstHalfAtomForces_->quantity(),
|
|
myNodalAtomicLambdaForce,myNodalAtomicLambdaPower,0.5*dt);
|
|
|
|
if (full_prediction())
|
|
atomThermostatForces_->fix_quantity();
|
|
|
|
// SPLIT OUT FUNCTION TO CREATE DELTA VARIABLES IN BASES, ONLY NEED THESE
|
|
// update predicted nodal variables for second half of time step
|
|
// velocity
|
|
this->add_to_momentum(myNodalAtomicLambdaForce,deltaMomentum_,0.5*dt);
|
|
atc_->apply_inverse_mass_matrix(deltaMomentum_,VELOCITY);
|
|
velocity_ += deltaMomentum_;
|
|
// temperature
|
|
this->add_to_energy(myNodalAtomicLambdaPower,deltaEnergy2_,0.5*dt);
|
|
// following manipulations performed this way for efficiency
|
|
deltaEnergy1_ += deltaEnergy2_;
|
|
atc_->apply_inverse_mass_matrix(deltaEnergy1_,TEMPERATURE);
|
|
temperature_ += deltaEnergy1_;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// apply_post_corrector:
|
|
// apply the thermostat to the atoms in the second part
|
|
// of the corrector step of the Verlet algorithm
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::apply_post_corrector(double dt)
|
|
{
|
|
// remove predicted power effects
|
|
// velocity
|
|
DENS_MAT & myVelocity(velocity_.set_quantity());
|
|
myVelocity -= deltaMomentum_;
|
|
// temperature
|
|
DENS_MAT & myTemperature(temperature_.set_quantity());
|
|
atc_->apply_inverse_mass_matrix(deltaEnergy2_,TEMPERATURE);
|
|
myTemperature -= deltaEnergy2_;
|
|
|
|
// set up equation and update lambda
|
|
this->compute_lambda(dt);
|
|
|
|
// apply lambda force to atoms and compute instantaneous lambda power for second half of time step
|
|
DENS_MAT & nodalAtomicLambdaForce(nodalAtomicLambdaForce_->set_quantity());
|
|
DENS_MAT & myNodalAtomicLambdaPower(nodalAtomicLambdaPower_->set_quantity());
|
|
// allow computation of force applied by lambda using current velocities
|
|
atomThermostatForces_->unfix_quantity();
|
|
atomThermostatForces_->quantity();
|
|
atomThermostatForces_->fix_quantity();
|
|
apply_to_atoms(atomVelocities_,nodalAtomicMomentum_,nodalAtomicEnergy_,
|
|
atomRegulatorForces_->quantity(),
|
|
nodalAtomicLambdaForce,myNodalAtomicLambdaPower,0.5*dt);
|
|
|
|
// finalize filtered lambda force and power by adding latest contribution
|
|
timeFilter_->apply_post_step2(lambdaForceFiltered_->set_quantity(),
|
|
nodalAtomicLambdaForce,dt);
|
|
timeFilter_->apply_post_step2(lambdaPowerFiltered_->set_quantity(),
|
|
myNodalAtomicLambdaPower,dt);
|
|
|
|
// update nodal variables for second half of time step
|
|
// velocity
|
|
this->add_to_momentum(nodalAtomicLambdaForce,deltaMomentum_,0.5*dt);
|
|
atc_->apply_inverse_mass_matrix(deltaMomentum_,VELOCITY);
|
|
velocity_ += deltaMomentum_;
|
|
// temperature
|
|
this->add_to_energy(myNodalAtomicLambdaPower,deltaEnergy2_,0.5*dt);
|
|
atc_->apply_inverse_mass_matrix(deltaEnergy2_,TEMPERATURE);
|
|
myTemperature += deltaEnergy2_;
|
|
|
|
|
|
isFirstTimestep_ = false;
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// compute_lambda:
|
|
// sets up and solves linear system for lambda, if the
|
|
// bool is true it iterators to a non-linear solution
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::compute_lambda(double dt,
|
|
bool iterateSolution)
|
|
{
|
|
// ITERATIVE SOLUTION
|
|
}
|
|
|
|
//--------------------------------------------------------
|
|
// output:
|
|
// adds all relevant output to outputData
|
|
//--------------------------------------------------------
|
|
void KinetoThermostatGlcFs::output(OUTPUT_LIST & outputData)
|
|
{
|
|
// DO NOT CALL INDIVIDUAL REGULATORS
|
|
// OUTPUT TOTAL FORCE AND TOTAL POWER
|
|
// OUTPUT EACH LAMBDA
|
|
}
|
|
|
|
|
|
};
|