2013-08-08 05:34:54 +08:00
|
|
|
// ATC transfer headers
|
|
|
|
#include "ThermalTimeIntegrator.h"
|
|
|
|
#include "TransferOperator.h"
|
|
|
|
#include "ATC_Coupling.h"
|
|
|
|
#include "TimeFilter.h"
|
|
|
|
#include "ATC_Error.h"
|
|
|
|
#include "PerAtomQuantityLibrary.h"
|
|
|
|
|
|
|
|
namespace ATC {
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Class ThermalTimeIntegrator
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Constructor
|
|
|
|
//--------------------------------------------------------
|
|
|
|
ThermalTimeIntegrator::ThermalTimeIntegrator(ATC_Coupling * atc,
|
|
|
|
TimeIntegrationType timeIntegrationType) :
|
|
|
|
TimeIntegrator(atc, timeIntegrationType)
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// modify
|
|
|
|
// parses inputs and modifies state of the integrator
|
|
|
|
//--------------------------------------------------------
|
|
|
|
bool ThermalTimeIntegrator::modify(int narg, char **arg)
|
|
|
|
{
|
|
|
|
bool foundMatch = false;
|
|
|
|
int argIndex = 0;
|
|
|
|
|
|
|
|
// time integration scheme
|
2013-08-22 07:06:07 +08:00
|
|
|
/*! \page man_thermal_time_integration fix_modify AtC time_integration (thermal)
|
2013-08-08 05:34:54 +08:00
|
|
|
\section syntax
|
|
|
|
fix_modify AtC time_integration <descriptor> \n
|
|
|
|
- descriptor (string) = time integration type \n
|
|
|
|
|
|
|
|
various time integration methods for the finite elements\n
|
|
|
|
\section description
|
2013-08-22 07:06:07 +08:00
|
|
|
gear - atomic velocity update with 2nd order Verlet, nodal temperature update with 3rd or 4th order Gear, thermostats based on controlling power \n
|
|
|
|
fractional_step - atomic velocity update with 2nd order Verlet, mixed nodal temperature update, 3/4 Gear for continuum and 2 Verlet for atomic contributions, thermostats based on controlling discrete energy changes\n
|
2013-08-08 05:34:54 +08:00
|
|
|
\section examples
|
|
|
|
<TT> fix_modify atc time_integration gear </TT> \n
|
|
|
|
<TT> fix_modify atc time_integration fractional_step </TT> \n
|
|
|
|
\section description
|
|
|
|
\section related
|
2013-08-22 07:06:07 +08:00
|
|
|
see \ref man_fix_atc
|
2013-08-08 05:34:54 +08:00
|
|
|
\section default
|
2013-08-22 07:06:07 +08:00
|
|
|
none
|
2013-08-08 05:34:54 +08:00
|
|
|
*/
|
|
|
|
if (strcmp(arg[argIndex],"gear")==0) {
|
|
|
|
timeIntegrationType_ = GEAR;
|
|
|
|
needReset_ = true;
|
|
|
|
foundMatch = true;
|
|
|
|
}
|
|
|
|
else if (strcmp(arg[argIndex],"fractional_step")==0) {
|
|
|
|
timeIntegrationType_ = FRACTIONAL_STEP;
|
|
|
|
needReset_ = true;
|
|
|
|
foundMatch = true;
|
|
|
|
}
|
|
|
|
return foundMatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// construct_methods
|
|
|
|
// creates algorithm objects
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegrator::construct_methods()
|
|
|
|
{
|
|
|
|
if (atc_->reset_methods()) {
|
|
|
|
if (timeIntegrationMethod_) delete timeIntegrationMethod_;
|
|
|
|
|
|
|
|
if (timeFilterManager_->need_reset()) {
|
|
|
|
switch (timeIntegrationType_) {
|
|
|
|
case GEAR: {
|
|
|
|
timeFilter_ = timeFilterManager_->construct(TimeFilterManager::IMPLICIT);
|
|
|
|
atc_->set_mass_mat_time_filter(TEMPERATURE,TimeFilterManager::EXPLICIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FRACTIONAL_STEP: {
|
|
|
|
timeFilter_ = timeFilterManager_->construct(TimeFilterManager::EXPLICIT_IMPLICIT);
|
|
|
|
atc_->set_mass_mat_time_filter(TEMPERATURE,TimeFilterManager::EXPLICIT_IMPLICIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
throw ATC_Error("Uknown time integration type in ThermalTimeIntegrator::Initialize()");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (timeFilterManager_->filter_dynamics()) {
|
|
|
|
switch (timeIntegrationType_) {
|
|
|
|
case GEAR: {
|
|
|
|
timeIntegrationMethod_ = new ThermalTimeIntegratorGearFiltered(this);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FRACTIONAL_STEP: {
|
|
|
|
timeIntegrationMethod_ = new ThermalTimeIntegratorFractionalStepFiltered(this);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
throw ATC_Error("Uknown time integration type in ThermalTimeIntegrator::Initialize()");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
switch (timeIntegrationType_) {
|
|
|
|
case GEAR: {
|
|
|
|
timeIntegrationMethod_ = new ThermalTimeIntegratorGear(this);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case FRACTIONAL_STEP: {
|
|
|
|
timeIntegrationMethod_ = new ThermalTimeIntegratorFractionalStep(this);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
throw ATC_Error("Uknown time integration type in ThermalTimeIntegrator::Initialize()");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// pack_fields
|
|
|
|
// add persistent variables to data list
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegrator::pack_fields(RESTART_LIST & data)
|
|
|
|
{
|
|
|
|
data["NodalAtomicPowerFiltered"] = & nodalAtomicPowerFiltered_.set_quantity();
|
|
|
|
data["NodalAtomicEnergyFiltered"] = & nodalAtomicEnergyFiltered_.set_quantity();
|
|
|
|
TimeIntegrator::pack_fields(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Class ThermalIntegrationMethod
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Constructor
|
|
|
|
// Grab data from ATC
|
|
|
|
//--------------------------------------------------------
|
|
|
|
ThermalIntegrationMethod::ThermalIntegrationMethod(ThermalTimeIntegrator * thermalTimeIntegrator) :
|
|
|
|
TimeIntegrationMethod(thermalTimeIntegrator),
|
|
|
|
timeFilter_(thermalTimeIntegrator->time_filter()),
|
|
|
|
temperature_(atc_->field(TEMPERATURE)),
|
|
|
|
temperatureRoc_(atc_->field_roc(TEMPERATURE)),
|
|
|
|
temperature2Roc_(atc_->field_2roc(TEMPERATURE)),
|
|
|
|
nodalAtomicTemperatureOut_(atc_->nodal_atomic_field(TEMPERATURE)),
|
|
|
|
nodalAtomicTemperature_(NULL),
|
|
|
|
temperatureRhs_(atc_->field_rhs(TEMPERATURE)),
|
|
|
|
nodalAtomicPowerOut_(atc_->nodal_atomic_field_roc(TEMPERATURE))
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// construct_transfers
|
|
|
|
// Grab existing managed quantities,
|
|
|
|
// create the rest
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalIntegrationMethod::construct_transfers()
|
|
|
|
{
|
|
|
|
nodalAtomicTemperature_ =
|
|
|
|
(atc_->interscale_manager()).dense_matrix("NodalAtomicTemperature");
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Class ThermalIntegratorGear
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Constructor
|
|
|
|
//--------------------------------------------------------
|
|
|
|
ThermalTimeIntegratorGear::ThermalTimeIntegratorGear(ThermalTimeIntegrator * thermalTimeIntegrator) :
|
|
|
|
ThermalIntegrationMethod(thermalTimeIntegrator),
|
|
|
|
nodalAtomicPowerFiltered_(thermalTimeIntegrator->nodal_atomic_power_filtered())
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// construct_transfers
|
|
|
|
// Grab existing managed quantities,
|
|
|
|
// create the rest
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGear::construct_transfers()
|
|
|
|
{
|
|
|
|
ThermalIntegrationMethod::construct_transfers();
|
|
|
|
InterscaleManager & interscaleManager = atc_->interscale_manager();
|
|
|
|
|
|
|
|
// add in power computation
|
|
|
|
DotTwiceKineticEnergy * dotTwiceKineticEnergy =
|
|
|
|
new DotTwiceKineticEnergy(atc_);
|
|
|
|
interscaleManager.add_per_atom_quantity(dotTwiceKineticEnergy,"DotTwiceKineticEnergy");
|
|
|
|
nodalAtomicPower_ = new AtfShapeFunctionRestriction(atc_,
|
|
|
|
dotTwiceKineticEnergy,
|
|
|
|
interscaleManager.per_atom_sparse_matrix("Interpolant"));
|
|
|
|
interscaleManager.add_dense_matrix(nodalAtomicPower_,"NodalAtomicPower");
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// initialize
|
|
|
|
// initialize all data
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGear::initialize()
|
|
|
|
{
|
|
|
|
ThermalIntegrationMethod::initialize();
|
|
|
|
|
|
|
|
// sets up time filter for cases where variables temporally filtered
|
|
|
|
// this time integrator should use an implicit filter
|
|
|
|
TimeFilterManager * timeFilterManager = atc_->time_filter_manager();
|
|
|
|
if (timeFilterManager->need_reset()) {
|
|
|
|
// Some time filters need the old value for the power
|
|
|
|
timeFilter_->initialize(nodalAtomicPower_->quantity());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!timeFilterManager->end_equilibrate()) {
|
|
|
|
nodalAtomicPowerFiltered_.reset(atc_->num_nodes(),1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!timeFilterManager->filter_dynamics()) {
|
|
|
|
temperatureRhs_ = nodalAtomicPower_->quantity();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// pre_initial_integrate2
|
|
|
|
/// time integration before Verlet step 1
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGear::pre_initial_integrate2(double dt)
|
|
|
|
{
|
|
|
|
// Predict nodal temperatures and time derivatives based on FE data
|
|
|
|
// use 3rd order Gear
|
|
|
|
gear1_3_predict(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.quantity(),dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// post_final_integrate1
|
|
|
|
// time integration after Verlet step 2
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGear::post_final_integrate1(double dt)
|
|
|
|
{
|
|
|
|
const DENS_MAT & myNodalAtomicPower(nodalAtomicPower_->quantity());
|
|
|
|
timeFilter_->apply_post_step2(nodalAtomicPowerFiltered_.set_quantity(),
|
|
|
|
myNodalAtomicPower,dt);
|
|
|
|
temperatureRhs_ += myNodalAtomicPower;
|
|
|
|
|
|
|
|
// Finish updating temperature
|
|
|
|
_temperatureResidual_.resize(atc_->num_nodes(),1);
|
|
|
|
atc_->apply_inverse_mass_matrix(temperatureRhs_.quantity(),
|
|
|
|
_temperatureResidual_,
|
|
|
|
TEMPERATURE);
|
|
|
|
_temperatureResidual_ -= temperatureRoc_.quantity();
|
|
|
|
_temperatureResidual_ *= dt;
|
|
|
|
|
|
|
|
gear1_3_correct(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.set_quantity(),
|
|
|
|
_temperatureResidual_,dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// post_process
|
|
|
|
// do any post-processing calculations required for
|
|
|
|
// output phase
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGear::post_process()
|
|
|
|
{
|
|
|
|
nodalAtomicPowerOut_ = nodalAtomicPower_->quantity();
|
|
|
|
nodalAtomicTemperatureOut_ = nodalAtomicTemperature_->quantity();
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// finish
|
|
|
|
// finalize state of nodal atomic quantities
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGear::finish()
|
|
|
|
{
|
|
|
|
post_process();
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Class ThermalTimeIntegratorGearFiltered
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Constructor
|
|
|
|
// Grab data from ATC
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
ThermalTimeIntegratorGearFiltered::ThermalTimeIntegratorGearFiltered(ThermalTimeIntegrator * thermalTimeIntegrator) :
|
|
|
|
ThermalTimeIntegratorGear(thermalTimeIntegrator),
|
|
|
|
temperature3Roc_(atc_->field_3roc(TEMPERATURE))
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
|
|
|
|
// specifically if history data is required and we need another time filter object for the fields
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// pre_initial_integrate2
|
|
|
|
// time integration before Verlet step 1
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGearFiltered::pre_initial_integrate2(double dt)
|
|
|
|
{
|
|
|
|
// Predict nodal temperatures and time derivatives based on FE data
|
|
|
|
// use 3rd order Gear
|
|
|
|
gear1_4_predict(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.set_quantity(),
|
|
|
|
temperature3Roc_.quantity(),dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// post_final_integrate1
|
|
|
|
// first time integration computations
|
|
|
|
// after Verlet step 2
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGearFiltered::post_final_integrate1(double dt)
|
|
|
|
{
|
|
|
|
DENS_MAT & myNodalAtomicPowerFiltered(nodalAtomicPowerFiltered_.set_quantity());
|
|
|
|
timeFilter_->apply_post_step2(myNodalAtomicPowerFiltered,nodalAtomicPower_->quantity(),dt);
|
|
|
|
temperatureRhs_ += myNodalAtomicPowerFiltered;
|
|
|
|
|
|
|
|
// Finish updating temperature
|
|
|
|
_temperatureResidual_.resize(atc_->num_nodes(),1);
|
|
|
|
atc_->apply_inverse_mass_matrix(temperatureRhs_.quantity(),
|
|
|
|
_temperatureResidual_,
|
|
|
|
TEMPERATURE);
|
|
|
|
_temperatureResidual_ -= temperatureRoc_.quantity();
|
|
|
|
_temperatureResidual_ *= dt;
|
|
|
|
gear1_4_correct(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.set_quantity(),
|
|
|
|
temperature3Roc_.set_quantity(),
|
|
|
|
_temperatureResidual_,dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// post_final_integrate3
|
|
|
|
// third time integration computations
|
|
|
|
// after Verlet step 2
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGearFiltered::post_final_integrate3(double dt)
|
|
|
|
{
|
|
|
|
// update filtered atomic temperature
|
|
|
|
timeFilter_->apply_post_step2(nodalAtomicTemperatureOut_.set_quantity(),
|
|
|
|
nodalAtomicTemperature_->quantity(),dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// post_process
|
|
|
|
// do any post-processing calculations required for
|
|
|
|
// output phase
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorGearFiltered::post_process()
|
|
|
|
{
|
|
|
|
nodalAtomicPowerOut_ = nodalAtomicPowerFiltered_.quantity();
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Class ThermalIntegratorFractionalStep
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Constructor
|
|
|
|
// Grab data from ATC
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
ThermalTimeIntegratorFractionalStep::ThermalTimeIntegratorFractionalStep(ThermalTimeIntegrator * thermalTimeIntegrator) :
|
|
|
|
ThermalIntegrationMethod(thermalTimeIntegrator),
|
|
|
|
nodalAtomicEnergyFiltered_(thermalTimeIntegrator->nodal_atomic_energy_filtered()),
|
|
|
|
nodalAtomicPowerFiltered_(thermalTimeIntegrator->nodal_atomic_power_filtered()),
|
|
|
|
atomicTemperatureDelta_(atc_->num_nodes(),1),
|
|
|
|
nodalAtomicEnergy_(NULL),
|
|
|
|
nodalAtomicEnergyOld_(atc_->num_nodes(),1),
|
|
|
|
nodalAtomicTemperatureOld_(atc_->num_nodes(),1)
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// construct_transfers
|
|
|
|
// Grab existing managed quantities,
|
|
|
|
// create the rest
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::construct_transfers()
|
|
|
|
{
|
|
|
|
ThermalIntegrationMethod::construct_transfers();
|
|
|
|
InterscaleManager & interscaleManager(atc_->interscale_manager());
|
|
|
|
nodalAtomicEnergy_ = interscaleManager.dense_matrix("NodalAtomicEnergy");
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// initialize
|
|
|
|
// initialize all data
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::initialize()
|
|
|
|
{
|
|
|
|
ThermalIntegrationMethod::initialize();
|
|
|
|
|
|
|
|
// initial power to zero
|
|
|
|
nodalAtomicPower_.reset(atc_->num_nodes(),1);
|
|
|
|
|
|
|
|
// sets up time filter for cases where variables temporally filtered
|
|
|
|
// this time integrator should use Crank-Nicholson filter for 2nd order accuracy
|
|
|
|
TimeFilterManager * timeFilterManager = atc_->time_filter_manager();
|
|
|
|
if (timeFilterManager->need_reset()) {
|
|
|
|
// the form of this integrator implies no time filters that require history data can be used
|
|
|
|
timeFilter_->initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
// sets up time filter for post-processing the filtered power
|
|
|
|
// this time integrator should use an explicit-implicit filter
|
|
|
|
// to mirror the 2nd order Verlet integration scheme
|
|
|
|
// It requires no history information so initial value just sizes arrays
|
|
|
|
if (!timeFilterManager->end_equilibrate()) {
|
|
|
|
// implies an initial condition of the instantaneous atomic energy
|
|
|
|
// for the corresponding filtered variable, consistent with the temperature
|
|
|
|
nodalAtomicEnergyFiltered_ = nodalAtomicEnergy_->quantity();
|
|
|
|
nodalAtomicPowerFiltered_.reset(atc_->num_nodes(),1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// pre_initial_integrate1
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::pre_initial_integrate1(double dt)
|
|
|
|
{
|
|
|
|
const DENS_MAT & myNodalAtomicEnergy(nodalAtomicEnergy_->quantity());
|
|
|
|
// updated filtered energy using explicit-implicit scheme
|
|
|
|
timeFilter_->apply_pre_step1(nodalAtomicEnergyFiltered_.set_quantity(),
|
|
|
|
myNodalAtomicEnergy,dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// pre_initial_integrate2
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::pre_initial_integrate2(double dt)
|
|
|
|
{
|
|
|
|
// used for updating change in temperature from mass matrix change
|
|
|
|
this->compute_old_time_data();
|
|
|
|
|
|
|
|
// update FE contributions
|
|
|
|
apply_gear_predictor(dt);
|
|
|
|
|
|
|
|
// update filtered nodal atomic power
|
|
|
|
|
|
|
|
// that way thermostat and integrator can be consistent
|
|
|
|
timeFilter_->apply_pre_step1(nodalAtomicPowerFiltered_.set_quantity(),
|
|
|
|
nodalAtomicPower_,dt);
|
|
|
|
|
|
|
|
// store current energy for use later
|
|
|
|
nodalAtomicPower_ = nodalAtomicEnergy_->quantity();
|
|
|
|
nodalAtomicPower_ *= -1.;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// pre_final_integrate1
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::pre_final_integrate1(double dt)
|
|
|
|
{
|
|
|
|
|
|
|
|
// before the new rhs is computed but after atomic velocity is updated
|
|
|
|
// to allow for general notions of temperature beyond kinetic.
|
|
|
|
// compute change in restricted atomic energy
|
|
|
|
nodalAtomicPower_ += nodalAtomicEnergy_->quantity();
|
|
|
|
|
|
|
|
// update FE temperature with change in temperature from MD
|
|
|
|
compute_temperature_delta(nodalAtomicPower_,dt);
|
|
|
|
temperature_ += atomicTemperatureDelta_.quantity();
|
|
|
|
|
|
|
|
// approximation to power for output
|
|
|
|
nodalAtomicPower_ /= dt;
|
|
|
|
timeFilter_->apply_post_step1(nodalAtomicPowerFiltered_.set_quantity(),
|
|
|
|
nodalAtomicPower_,dt);
|
|
|
|
|
|
|
|
// make sure nodes are fixed
|
|
|
|
atc_->set_fixed_nodes();
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// post_final_integrate1
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::post_final_integrate1(double dt)
|
|
|
|
{
|
|
|
|
// Finish updating temperature with FE contributions
|
|
|
|
atc_->apply_inverse_mass_matrix(temperatureRhs_.quantity(),
|
|
|
|
_temperatureResidual_,TEMPERATURE);
|
|
|
|
_temperatureResidual_ -= temperatureRoc_.quantity();
|
|
|
|
_temperatureResidual_ *= dt;
|
|
|
|
apply_gear_corrector(_temperatureResidual_,dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// post_final_integrate3
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::post_final_integrate3(double dt)
|
|
|
|
{
|
|
|
|
// update filtered atomic energy
|
|
|
|
timeFilter_->apply_post_step1(nodalAtomicEnergyFiltered_.set_quantity(),
|
|
|
|
nodalAtomicEnergy_->quantity(),dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// output
|
|
|
|
// add variables to output list
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::post_process()
|
|
|
|
{
|
|
|
|
nodalAtomicPowerOut_ = nodalAtomicPower_;
|
|
|
|
nodalAtomicTemperatureOut_ = nodalAtomicTemperature_->quantity();
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// finish
|
|
|
|
// finalize state of nodal atomic quantities
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::finish()
|
|
|
|
{
|
|
|
|
post_process();
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// apply_gear_predictor
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::apply_gear_predictor(double dt)
|
|
|
|
{
|
|
|
|
gear1_3_predict(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.quantity(),dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// apply_gear_corrector
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::apply_gear_corrector(const DENS_MAT & R_theta, double dt)
|
|
|
|
{
|
|
|
|
gear1_3_correct(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.set_quantity(),
|
|
|
|
R_theta,dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// compute_old_time_data
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::compute_old_time_data()
|
|
|
|
{
|
|
|
|
const DENS_MAT & myNodalAtomicEnergy(nodalAtomicEnergy_->quantity());
|
|
|
|
atc_->apply_inverse_mass_matrix(myNodalAtomicEnergy,
|
|
|
|
nodalAtomicTemperatureOld_.set_quantity(),
|
|
|
|
TEMPERATURE);
|
|
|
|
nodalAtomicEnergyOld_ = myNodalAtomicEnergy;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// compute_temperature_delta
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStep::compute_temperature_delta(const DENS_MAT & atomicEnergyDelta,
|
|
|
|
double dt)
|
|
|
|
{
|
|
|
|
DENS_MAT & myAtomicTemperatureDelta(atomicTemperatureDelta_.set_quantity());
|
|
|
|
myAtomicTemperatureDelta = nodalAtomicEnergyOld_.quantity() + atomicEnergyDelta;
|
|
|
|
atc_->apply_inverse_mass_matrix(myAtomicTemperatureDelta,
|
|
|
|
TEMPERATURE);
|
|
|
|
myAtomicTemperatureDelta += -1.*(nodalAtomicTemperatureOld_.quantity());
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Class ThermalTimeIntegratorFracionalStepFiltered
|
|
|
|
//--------------------------------------------------------
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Constructor
|
|
|
|
// Grab data from ATC
|
|
|
|
//--------------------------------------------------------
|
|
|
|
|
|
|
|
ThermalTimeIntegratorFractionalStepFiltered::ThermalTimeIntegratorFractionalStepFiltered(ThermalTimeIntegrator * thermalTimeIntegrator) :
|
|
|
|
ThermalTimeIntegratorFractionalStep(thermalTimeIntegrator),
|
|
|
|
temperature3Roc_(atc_->field_3roc(TEMPERATURE))
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// Destructor
|
|
|
|
//--------------------------------------------------------
|
|
|
|
ThermalTimeIntegratorFractionalStepFiltered::~ThermalTimeIntegratorFractionalStepFiltered()
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// pre_initial_integrate1
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStepFiltered::pre_initial_integrate1(double dt)
|
|
|
|
{
|
|
|
|
// determine change in temperature if no forces were applied over this timestep
|
|
|
|
|
|
|
|
// relevant coefficients from time filter
|
|
|
|
double coefF1 = timeFilter_->filtered_coefficient_pre_s1(dt);
|
|
|
|
double coefF2 = timeFilter_->filtered_coefficient_post_s1(dt);
|
|
|
|
double coefU1 = timeFilter_->unfiltered_coefficient_pre_s1(dt);
|
|
|
|
double coefU2 = timeFilter_->unfiltered_coefficient_post_s1(dt);
|
|
|
|
|
|
|
|
DENS_MAT & myAtomicTemperatureDelta(atomicTemperatureDelta_.set_quantity());
|
|
|
|
DENS_MAT & myNodalAtomicEnergyFiltered(nodalAtomicEnergyFiltered_.set_quantity());
|
|
|
|
const DENS_MAT & myNodalAtomicEnergy(nodalAtomicEnergy_->quantity());
|
|
|
|
|
|
|
|
// composite from change after two step update of current filtered energy
|
|
|
|
myAtomicTemperatureDelta = (coefF1*coefF2-1.)*myNodalAtomicEnergyFiltered;
|
|
|
|
// change in filtered temperature from current energy from this and next time levels
|
|
|
|
myAtomicTemperatureDelta += (coefU1*coefF2+coefU2)*myNodalAtomicEnergy;
|
|
|
|
|
|
|
|
// updated filtered energy using explicit-implicit scheme
|
|
|
|
// nodalAtomicEnergy_ is either set from initialization or from the end of the last timestep
|
|
|
|
timeFilter_->apply_pre_step1(myNodalAtomicEnergyFiltered,myNodalAtomicEnergy,dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// output
|
|
|
|
// add variables to output list
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStepFiltered::output(OUTPUT_LIST & outputData)
|
|
|
|
{
|
|
|
|
atc_->apply_inverse_md_mass_matrix(nodalAtomicEnergyFiltered_.quantity(),
|
|
|
|
nodalAtomicTemperatureOut_.set_quantity(),
|
|
|
|
TEMPERATURE);
|
|
|
|
DENS_MAT & nodalAtomicPower(nodalAtomicPowerFiltered_.set_quantity());
|
|
|
|
if ((atc_->lammps_interface())->rank_zero()) {
|
|
|
|
outputData["NodalAtomicPower"] = &nodalAtomicPower;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// apply_gear_predictor
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStepFiltered::apply_gear_predictor(double dt)
|
|
|
|
{
|
|
|
|
gear1_4_predict(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.set_quantity(),
|
|
|
|
temperature3Roc_.quantity(),dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// apply_gear_corrector
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStepFiltered::apply_gear_corrector(const DENS_MAT & R_theta, double dt)
|
|
|
|
{
|
|
|
|
gear1_4_correct(temperature_.set_quantity(),
|
|
|
|
temperatureRoc_.set_quantity(),
|
|
|
|
temperature2Roc_.set_quantity(),
|
|
|
|
temperature3Roc_.set_quantity(),
|
|
|
|
R_theta,dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// compute_temperature_delta
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStepFiltered::compute_old_time_data()
|
|
|
|
{
|
|
|
|
const DENS_MAT & myNodalAtomicEnergyFiltered(nodalAtomicEnergyFiltered_.quantity());
|
|
|
|
atc_->apply_inverse_mass_matrix(myNodalAtomicEnergyFiltered,
|
|
|
|
nodalAtomicTemperatureOld_.set_quantity(),
|
|
|
|
TEMPERATURE);
|
|
|
|
nodalAtomicEnergyOld_ = myNodalAtomicEnergyFiltered;
|
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------
|
|
|
|
// compute_old_time_data
|
|
|
|
//--------------------------------------------------------
|
|
|
|
void ThermalTimeIntegratorFractionalStepFiltered::compute_temperature_delta(const DENS_MAT & atomicEnergyDelta,
|
|
|
|
double dt)
|
|
|
|
{
|
|
|
|
DENS_MAT & myAtomicTemperatureDelta(atomicTemperatureDelta_.set_quantity());
|
|
|
|
double coefU2 = timeFilter_->unfiltered_coefficient_post_s1(dt);
|
|
|
|
myAtomicTemperatureDelta += nodalAtomicEnergyOld_.quantity() + coefU2*atomicEnergyDelta;
|
|
|
|
atc_->apply_inverse_mass_matrix(myAtomicTemperatureDelta,
|
|
|
|
TEMPERATURE);
|
|
|
|
myAtomicTemperatureDelta += -1.*nodalAtomicTemperatureOld_.quantity();
|
|
|
|
}
|
|
|
|
};
|