2013-08-08 05:34:54 +08:00
# 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 ) ,
2014-11-21 02:59:03 +08:00
couplingMaxIterations_ ( myCouplingMaxIterations )
2013-08-08 05:34:54 +08:00
{
// 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 ) {
2014-11-21 02:59:03 +08:00
DENS_MAN * lambdaForceFiltered = regulator_data ( " LambdaForceFiltered " , atc_ - > nsd ( ) ) ;
* lambdaForceFiltered = target ;
2013-08-08 05:34:54 +08:00
}
else if ( field = = TEMPERATURE ) {
2014-11-21 02:59:03 +08:00
DENS_MAN * lambdaPowerFiltered = regulator_data ( " LambdaPowerFiltered " , 1 ) ;
* lambdaPowerFiltered = target ;
2013-08-08 05:34:54 +08:00
}
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 ( )
{
2014-11-21 02:59:03 +08:00
// 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 ) ;
}
2013-08-08 05:34:54 +08:00
2014-11-21 02:59:03 +08:00
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 " ) ;
}
}
2013-08-08 05:34:54 +08:00
2014-11-21 02:59:03 +08:00
AtomicRegulator : : reset_method ( ) ;
}
else {
set_all_data_to_used ( ) ;
}
2013-08-08 05:34:54 +08:00
}
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
//--------------------------------------------------------
// Class VelocityRescaleCombined
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
// Grab references to ATC and kinetostat data
//--------------------------------------------------------
VelocityRescaleCombined : : VelocityRescaleCombined ( AtomicRegulator * kinetostat ) :
VelocityGlc ( kinetostat ) ,
velocity_ ( atc_ - > field ( VELOCITY ) ) ,
thermostatCorrection_ ( NULL )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
// do nothing
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// initialize
// initializes all data
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void VelocityRescaleCombined : : initialize ( )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
VelocityGlc : : initialize ( ) ;
thermostatCorrection_ = ( atc_ - > interscale_manager ( ) ) . dense_matrix ( " NodalAtomicFluctuatingMomentumRescaled " ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// set_kinetostat_rhs
// sets up the right-hand side of the
// kinetostat equations
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void VelocityRescaleCombined : : set_kinetostat_rhs ( DENS_MAT & rhs , double dt )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
rhs = ( ( atc_ - > mass_mat_md ( VELOCITY ) ) . quantity ( ) ) * ( velocity_ . quantity ( ) ) ;
rhs - = thermostatCorrection_ - > quantity ( ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
//--------------------------------------------------------
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// Class ThermostatRescaleCombined
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ThermostatRescaleCombined : : ThermostatRescaleCombined ( AtomicRegulator * thermostat ) :
ThermostatRescale ( thermostat ) ,
kinetostatCorrection_ ( NULL )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
// do nothing
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// initialize
// initializes all data
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void ThermostatRescaleCombined : : initialize ( )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
ThermostatRescale : : initialize ( ) ;
kinetostatCorrection_ = ( atc_ - > interscale_manager ( ) ) . dense_matrix ( " NodalAtomicCombinedRescaleThermostatError " ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// set_rhs:
// constructs the RHS vector with the target
// temperature
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void ThermostatRescaleCombined : : set_rhs ( DENS_MAT & rhs )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
ThermostatRescale : : set_rhs ( rhs ) ;
rhs - = kinetostatCorrection_ - > quantity ( ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
//--------------------------------------------------------
//--------------------------------------------------------
// 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 )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
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 ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// Destructor
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
KinetoThermostatRescale : : ~ KinetoThermostatRescale ( )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
if ( thermostat_ ) delete thermostat_ ;
if ( kinetostat_ ) delete kinetostat_ ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// constructor_transfers
// instantiates or obtains all dependency managed data
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void KinetoThermostatRescale : : construct_transfers ( )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
// 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 " ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// construct_rescale_thermostat
// constructs the appropriate rescaling thermostat
// varied through inheritance
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
ThermostatRescale * KinetoThermostatRescale : : construct_rescale_thermostat ( )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
return new ThermostatRescaleCombined ( atomicRegulator_ ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// initialize
// initializes all data
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void KinetoThermostatRescale : : initialize ( )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
KinetoThermostatShapeFunction : : initialize ( ) ;
thermostat_ - > initialize ( ) ;
kinetostat_ - > initialize ( ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
//--------------------------------------------------------
// 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_ ) ;
}
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// apply_lambda_to_atoms:
// applies the velocity rescale with an existing lambda
// note oldAtomicQuantity and dt are not used
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void KinetoThermostatRescale : : apply_to_atoms ( PerAtomQuantity < double > * atomVelocities )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
* atomVelocities = atomicFluctuatingVelocityRescaled_ - > quantity ( ) + atomicStreamingVelocity_ - > quantity ( ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// output:
// adds all relevant output to outputData
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void KinetoThermostatRescale : : output ( OUTPUT_LIST & outputData )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
thermostat_ - > output ( outputData ) ;
kinetostat_ - > output ( outputData ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// Class ThermostatRescaleMixedKePeCombined
//--------------------------------------------------------
//--------------------------------------------------------
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
ThermostatRescaleMixedKePeCombined : : ThermostatRescaleMixedKePeCombined ( AtomicRegulator * thermostat ) :
ThermostatRescaleMixedKePe ( thermostat ) ,
kinetostatCorrection_ ( NULL )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
// do nothing
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// initialize
// initializes all data
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void ThermostatRescaleMixedKePeCombined : : initialize ( )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
ThermostatRescaleMixedKePe : : initialize ( ) ;
kinetostatCorrection_ = ( atc_ - > interscale_manager ( ) ) . dense_matrix ( " NodalAtomicCombinedRescaleThermostatError " ) ;
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
// set_rhs:
// constructs the RHS vector with the target
// temperature
2013-08-08 05:34:54 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
void ThermostatRescaleMixedKePeCombined : : set_rhs ( DENS_MAT & rhs )
2013-08-23 07:31:09 +08:00
{
2014-11-21 02:59:03 +08:00
ThermostatRescaleMixedKePe : : set_rhs ( rhs ) ;
rhs - = kinetostatCorrection_ - > quantity ( ) ;
2013-08-23 07:31:09 +08:00
}
2014-11-21 02:59:03 +08:00
//--------------------------------------------------------
//--------------------------------------------------------
// Class KinetoThermostatRescaleMixedKePe
//--------------------------------------------------------
2013-08-23 07:31:09 +08:00
//--------------------------------------------------------
2014-11-21 02:59:03 +08:00
//--------------------------------------------------------
// Constructor
//--------------------------------------------------------
KinetoThermostatRescaleMixedKePe : : KinetoThermostatRescaleMixedKePe ( AtomicRegulator * kinetoThermostat ,
int couplingMaxIterations ) :
KinetoThermostatRescale ( kinetoThermostat , couplingMaxIterations )
2013-08-08 05:34:54 +08:00
{
2014-11-21 02:59:03 +08:00
// 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
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
// 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
2013-08-08 05:34:54 +08:00
}
2014-11-21 02:59:03 +08:00
2013-08-08 05:34:54 +08:00
} ;