lammps/lib/atc/KinetoThermostat.cpp

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
}
};