lammps/lib/atc/FieldManager.cpp

549 lines
24 KiB
C++

#include "FieldManager.h"
#include "ATC_Method.h"
#include "LammpsInterface.h"
#include "PerAtomQuantity.h"
#include "TransferOperator.h"
using std::string;
namespace ATC {
typedef PerAtomQuantity<double> PAQ;
//-----------------------------------------------------------------------------
//*
//-----------------------------------------------------------------------------
FieldManager::FieldManager(ATC_Method * atc):
atc_(atc),
interscaleManager_(atc->interscale_manager())
{};
//-----------------------------------------------------------------------------
//* restricted_atom_quantity
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::restricted_atom_quantity(FieldName field, string name, PAQ * atomicQuantity)
{
if (name == "default") { name = field_to_restriction_name(field); }
DENS_MAN * quantity = interscaleManager_.dense_matrix(name);
if (!quantity){
if (field == CHARGE_DENSITY) {
atomicQuantity = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_CHARGE);
}
else if (field == MASS_DENSITY) {
atomicQuantity = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_MASS);
}
else {
if (!atomicQuantity) {
throw ATC_Error("FieldManager::restricted_atom_quantity - need to supply PAQ if restricted quantity does not already exist");
}
}
quantity = new AtfShapeFunctionRestriction(atc_,atomicQuantity,atc_->accumulant());
interscaleManager_.add_dense_matrix(quantity,name);
}
return quantity;
}
//-----------------------------------------------------------------------------
//* restricted_atom_quantity
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::projected_atom_quantity(FieldName field,string name, PAQ * atomic, DIAG_MAN * normalization)
{
if (atc_->use_md_mass_normalization()) {
if (name == "default") { name = field_to_intrinsic_name(field); }
DENS_MAN * quantity = interscaleManager_.dense_matrix(name);
if (!quantity) {
DENS_MAN * restricted = restricted_atom_quantity(field,field_to_restriction_name(field),atomic);
quantity = new AtfShapeFunctionMdProjection(atc_,restricted,use_mass_matrix(field));
interscaleManager_.add_dense_matrix(quantity,name);
}
return quantity;
}
else {
if (name == "default") { name = field_to_string(field); }
DENS_MAN * quantity = interscaleManager_.dense_matrix(name);
if (quantity) return quantity;
if (atc_->kernel_on_the_fly()) {
if (atc_->kernel_based()) {
quantity = new OnTheFlyKernelAccumulationNormalized(atc_, atomic,
atc_->kernel_function(),
atc_->atom_coarsegraining_positions(),
normalization);
} else {
quantity = new OnTheFlyMeshAccumulationNormalized(atc_, atomic,
atc_->atom_coarsegraining_positions(),
normalization);
}
} else {
quantity = new AtfProjection(atc_, atomic,
atc_->accumulant(),
normalization);
}
interscaleManager_.add_dense_matrix(quantity,name);
return quantity;
}
}
//-----------------------------------------------------------------------------
//* referenced_projected_atom_quantity
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::referenced_projected_atom_quantity(FieldName field,string name, PAQ * atomic, DENS_MAN * reference, DIAG_MAN * normalization)
{
if (name == "default") { name = field_to_string(field); }
DENS_MAN * quantity = interscaleManager_.dense_matrix(name);
if (quantity) return quantity;
if (atc_->use_md_mass_normalization()) {
DENS_MAN * restricted = restricted_atom_quantity(field,field_to_restriction_name(field),atomic);
quantity = new AtfShapeFunctionMdProjectionReferenced(atc_,restricted,reference,use_mass_matrix(field));
}
else if (atc_->kernel_on_the_fly()) {
if (atc_->kernel_based()) {
quantity = new OnTheFlyKernelAccumulationNormalizedReferenced(atc_,
atomic,
atc_->kernel_function(),
atc_->atom_coarsegraining_positions(),
normalization,
reference);
} else {
quantity = new OnTheFlyMeshAccumulationNormalizedReferenced(atc_,
atomic,
atc_->atom_coarsegraining_positions(),
normalization,
reference);
}
} else {
quantity = new AtfProjectionReferenced(atc_, atomic,
atc_->accumulant(),
reference,
normalization);
}
interscaleManager_.add_dense_matrix(quantity,name);
return quantity;
}
//-----------------------------------------------------------------------------
//* scaled_projected_atom_quantity
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::scaled_projected_atom_quantity(FieldName field,string name, PAQ * atomic, double scale, DIAG_MAN * normalization)
{
if (name == "default") { name = field_to_string(field); }
DENS_MAN * quantity = interscaleManager_.dense_matrix(name);
if (quantity) return quantity;
if (atc_->use_md_mass_normalization()) {
DENS_MAN * restricted = restricted_atom_quantity(field,field_to_restriction_name(field),atomic);
quantity = new AtfShapeFunctionMdProjectionScaled(atc_,restricted,scale,use_mass_matrix(field));
}
else if (atc_->kernel_on_the_fly()) {
if (atc_->kernel_based()) {
quantity = new OnTheFlyKernelAccumulationNormalizedScaled(atc_, atomic,
atc_->kernel_function(),
atc_->atom_coarsegraining_positions(),
normalization,
scale);
} else {
quantity = new OnTheFlyMeshAccumulationNormalizedScaled(atc_, atomic,
atc_->atom_coarsegraining_positions(),
normalization,
scale);
}
} else {
quantity = new AtfProjectionScaled(atc_, atomic,
atc_->accumulant(),
scale,
normalization);
}
interscaleManager_.add_dense_matrix(quantity,name);
return quantity;
}
//-----------------------------------------------------------------------------
//* CHARGE_DENSITY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::charge_density(string name)
{
FundamentalAtomQuantity * atomic = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_CHARGE);
return projected_atom_quantity(CHARGE_DENSITY,name,atomic,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* MASS_DENSITY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::mass_density(string name)
{
FundamentalAtomQuantity * atomic = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_MASS);
return projected_atom_quantity(MASS_DENSITY,name,atomic,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* SPECIES_CONCENTRATION
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::species_concentration(string name)
{
PerAtomQuantity<double> * atomTypeVector = interscaleManager_.per_atom_quantity("atom_species_vector");
if (!atomTypeVector) {
atomTypeVector = new AtomTypeVector(atc_,atc_->type_list(),atc_->group_list());
interscaleManager_.add_per_atom_quantity(atomTypeVector,"atom_species_vector");
}
return projected_atom_quantity(SPECIES_CONCENTRATION,name,atomTypeVector,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* NUMBER_DENSITY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::number_density(string name)
{
PAQ * atomic = interscaleManager_.per_atom_quantity("atomNumber");
if (!atomic) {
atomic = new AtomNumber(atc_);
interscaleManager_.add_per_atom_quantity(atomic, "atomNumber");
}
return projected_atom_quantity(NUMBER_DENSITY,name,atomic,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* MOMENTUM
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::momentum(string name)
{
PAQ * atomic = interscaleManager_.per_atom_quantity("atomMomentum");
if (!atomic) {
atomic = new AtomicMomentum(atc_);
interscaleManager_.add_per_atom_quantity(atomic, "atomMomentum");
}
return projected_atom_quantity(MOMENTUM,name,atomic,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* VELOCITY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::velocity(string name)
{
if (name == "default") { name = field_to_string(VELOCITY); }
DENS_MAN * v = interscaleManager_.dense_matrix(name);
if (v) return v;
if (atc_->use_md_mass_normalization()) {
PAQ * atomic = interscaleManager_.per_atom_quantity("atomMomentum");
if (!atomic) {
atomic = new AtomicMomentum(atc_);
interscaleManager_.add_per_atom_quantity(atomic, "atomMomentum");
}
DENS_MAN * restricted = restricted_atom_quantity(VELOCITY,field_to_restriction_name(VELOCITY),atomic);
v = new AtfShapeFunctionMdProjection(atc_,restricted,VELOCITY);
}
else {
DENS_MAN* p = interscaleManager_.dense_matrix(field_to_string(MOMENTUM));
if (!p) p = nodal_atomic_field(MOMENTUM);
DENS_MAN* m = interscaleManager_.dense_matrix(field_to_string(MASS_DENSITY));
if (!m) m = nodal_atomic_field(MASS_DENSITY);
v = new DenseMatrixQuotient(p,m);
}
interscaleManager_.add_dense_matrix(v,field_to_string(VELOCITY));
return v;
}
//-----------------------------------------------------------------------------
//* PROJECTED_VELOCITY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::projected_velocity(string name)
{
FundamentalAtomQuantity * atomic = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_VELOCITY);
return projected_atom_quantity(PROJECTED_VELOCITY,name,atomic,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* DISPLACEMENT
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::displacement(string name)
{
if (name == "default") { name = field_to_string(DISPLACEMENT); }
DENS_MAN * u = interscaleManager_.dense_matrix(name);
if (u) return u;
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicMassWeightedDisplacement");
if (!atomic) {
FundamentalAtomQuantity * atomMasses = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_MASS);
FundamentalAtomQuantity * atomPositions = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_POSITION);
atomic = new AtomicMassWeightedDisplacement(atc_,atomPositions, atomMasses, atc_->atom_reference_positions(), INTERNAL);
interscaleManager_.add_per_atom_quantity(atomic,"AtomicMassWeightedDisplacement");
}
if (atc_->use_md_mass_normalization()) {
DENS_MAN * restricted = restricted_atom_quantity(DISPLACEMENT,field_to_restriction_name(DISPLACEMENT),atomic);
u = new AtfShapeFunctionMdProjection(atc_,restricted,VELOCITY);
}
else {
DENS_MAN * q = NULL;
if (atc_->kernel_on_the_fly()) {
if (atc_->kernel_based()) {
q = new OnTheFlyKernelAccumulationNormalized(atc_, atomic,
atc_->kernel_function(),
atc_->atom_coarsegraining_positions(),
atc_->accumulant_inverse_volumes());
} else {
q = new OnTheFlyMeshAccumulationNormalized(atc_, atomic,
atc_->atom_coarsegraining_positions(),
atc_->accumulant_inverse_volumes());
}
} else {
q = new AtfProjection(atc_, atomic,
atc_->accumulant(),
atc_->accumulant_inverse_volumes());
}
interscaleManager_.add_dense_matrix(q,"CoarseGrainedAMWD");
DENS_MAN* m = interscaleManager_.dense_matrix(field_to_string(MASS_DENSITY));
u = new DenseMatrixQuotient(q,m);
}
interscaleManager_.add_dense_matrix(u,name);
return u;
}
//-----------------------------------------------------------------------------
//* REFERENCE_POTENTIAL_ENERGY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::reference_potential_energy(string name)
{
DENS_MAN * rpe = interscaleManager_.dense_matrix(field_to_string(REFERENCE_POTENTIAL_ENERGY));
if (! rpe ) {
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicReferencePotential");
if (!atomic) {
atomic = new AtcAtomQuantity<double>(atc_);
interscaleManager_.add_per_atom_quantity(atomic, "AtomicReferencePotential");
atomic->set_memory_type(PERSISTENT);
}
SPAR_MAN * referenceAccumulant = interscaleManager_.sparse_matrix("ReferenceAccumulant");
if (!referenceAccumulant) {
referenceAccumulant = new SPAR_MAN();
referenceAccumulant->set_memory_type(PERSISTENT);
interscaleManager_.add_sparse_matrix(referenceAccumulant,
"ReferenceAccumulant");
}
DIAG_MAN * referenceAccumulantInverseVolumes = interscaleManager_.diagonal_matrix("ReferenceAccumulantInverseVolumes");
if (!referenceAccumulantInverseVolumes) {
referenceAccumulantInverseVolumes = new DIAG_MAN();
referenceAccumulantInverseVolumes->set_memory_type(PERSISTENT);
interscaleManager_.add_diagonal_matrix(referenceAccumulantInverseVolumes,
"ReferenceAccumulantInverseVolumes");
}
rpe = new AtfProjection(atc_, atomic,
referenceAccumulant,
referenceAccumulantInverseVolumes);
interscaleManager_.add_dense_matrix(rpe,field_to_string(REFERENCE_POTENTIAL_ENERGY));
rpe->set_memory_type(PERSISTENT);
}
return rpe;
}
//-----------------------------------------------------------------------------
//* POTENTIAL_ENERGY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::potential_energy(string name)
{
PerAtomQuantity<double> * atomic = interscaleManager_.per_atom_quantity("AtomicPotentialEnergy");
if (!atomic) {
atomic = new ComputedAtomQuantity(atc_,(atc_->lammps_interface())->compute_pe_name(), atc_->pe_scale());
interscaleManager_.add_per_atom_quantity(atomic,"AtomicPotentialEnergy");
}
DENS_MAN * reference = interscaleManager_.dense_matrix(field_to_string(REFERENCE_POTENTIAL_ENERGY));
if (reference) {
return referenced_projected_atom_quantity(POTENTIAL_ENERGY,name,atomic,reference,atc_->accumulant_inverse_volumes());
}
else {
return projected_atom_quantity(POTENTIAL_ENERGY,name,atomic,atc_->accumulant_inverse_volumes());
}
}
//-----------------------------------------------------------------------------
//* TEMPERATURE
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::temperature(string name)
{
double Tcoef = 1./((atc_->nsd())*(atc_->lammps_interface())->kBoltzmann());
PAQ * atomic = per_atom_quantity("AtomicTwiceFluctuatingKineticEnergy");
return scaled_projected_atom_quantity(TEMPERATURE,name,atomic,Tcoef,atc_->accumulant_weights());
}
//-----------------------------------------------------------------------------
//* KINETIC_TEMPERATURE
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::kinetic_temperature(string name)
{
double Tcoef = 1./((atc_->nsd())*(atc_->lammps_interface())->kBoltzmann());
PAQ * atomic = per_atom_quantity("AtomicTwiceKineticEnergy");
return scaled_projected_atom_quantity(KINETIC_TEMPERATURE,name,atomic,Tcoef,atc_->accumulant_weights());
}
//-----------------------------------------------------------------------------
//* THERMAL_ENERGY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::thermal_energy(string name)
{
double Ecoef = 0.5*atc_->ke_scale();
PAQ * atomic = per_atom_quantity("AtomicTwiceFluctuatingKineticEnergy");
return scaled_projected_atom_quantity(THERMAL_ENERGY,name,atomic,Ecoef,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* KINETIC_ENERGY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::kinetic_energy(string name)
{
double Ecoef = 0.5*atc_->ke_scale();
PAQ * atomic = per_atom_quantity("AtomicTwiceKineticEnergy");
return scaled_projected_atom_quantity(KINETIC_ENERGY,name,atomic,Ecoef,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* CHARGE_FLUX
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::charge_flux(string name)
{
PAQ * atomic = per_atom_quantity("AtomicChargeVelocity");
return projected_atom_quantity(CHARGE_FLUX,name,atomic,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* SPECIES_FLUX
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::species_flux(string name)
{
PAQ * atomic = per_atom_quantity("AtomicSpeciesVelocity");
return projected_atom_quantity(SPECIES_FLUX,name,atomic,atc_->accumulant_inverse_volumes());
}
//-----------------------------------------------------------------------------
//* INTERNAL_ENERGY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::internal_energy(string name)
{
if (name == "default") { name = field_to_string(INTERNAL_ENERGY); }
DENS_MAN * te = thermal_energy(field_to_string(THERMAL_ENERGY));
DENS_MAN * pe = potential_energy(field_to_string(POTENTIAL_ENERGY));
DenseMatrixSum * ie = new DenseMatrixSum(te,pe);
interscaleManager_.add_dense_matrix(ie,name);
return ie;
}
//-----------------------------------------------------------------------------
//* ENERGY
//-----------------------------------------------------------------------------
DENS_MAN * FieldManager::energy(string name)
{
if (name == "default") { name = field_to_string(ENERGY); }
DENS_MAN * ke = kinetic_energy(field_to_string(KINETIC_ENERGY));
DENS_MAN * pe = potential_energy(field_to_string(POTENTIAL_ENERGY));
DenseMatrixSum * e = new DenseMatrixSum(ke,pe);
interscaleManager_.add_dense_matrix(e,name);
return e;
}
//=============================================================================
//* PER ATOM QUANTITIES
//=============================================================================
//-----------------------------------------------------------------------------
//* 2 KE '
//-----------------------------------------------------------------------------
PAQ * FieldManager::atomic_twice_fluctuating_kinetic_energy()
{
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicTwiceFluctuatingKineticEnergy");
if (!atomic) {
FundamentalAtomQuantity * atomMass = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_MASS);
FundamentalAtomQuantity * atomVelocity = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_VELOCITY);
PAQ * vbar = per_atom_quantity(field_to_prolongation_name(VELOCITY));
atomic = new TwiceFluctuatingKineticEnergy(atc_,atomVelocity,atomMass,vbar);
interscaleManager_.add_per_atom_quantity(atomic, "AtomicTwiceFluctuatingKineticEnergy");
}
return atomic;
}
//-----------------------------------------------------------------------------
//* 2 KE
//-----------------------------------------------------------------------------
PAQ * FieldManager::atomic_twice_kinetic_energy()
{
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicTwiceKineticEnergy");
if (!atomic) {
FundamentalAtomQuantity * atomMass = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_MASS);
FundamentalAtomQuantity * atomVelocity = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_VELOCITY);
atomic = new TwiceKineticEnergy(atc_,atomVelocity,atomMass);
interscaleManager_.add_per_atom_quantity(atomic, "AtomicTwiceKineticEnergy");
}
return atomic;
}
//-----------------------------------------------------------------------------
//* v'
//-----------------------------------------------------------------------------
PAQ * FieldManager::atomic_fluctuating_velocity()
{
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicFluctuatingVelocity");
if (!atomic) {
FundamentalAtomQuantity * atomVelocity = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_VELOCITY);
PAQ * atomMeanVelocity = per_atom_quantity(field_to_prolongation_name(VELOCITY));
atomic = new FluctuatingVelocity(atc_,atomVelocity,atomMeanVelocity);
interscaleManager_.add_per_atom_quantity(atomic, "AtomicFluctuatingVelocity");
}
return atomic;
}
//-----------------------------------------------------------------------------
//* q v'
//-----------------------------------------------------------------------------
PAQ * FieldManager::atomic_charge_velocity()
{
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicChargeVelocity");
if (!atomic) {
PAQ * atomVelocity = atomic_fluctuating_velocity();
FundamentalAtomQuantity * atomCharge = interscaleManager_.fundamental_atom_quantity(LammpsInterface::ATOM_CHARGE);
atomic = new ChargeVelocity(atc_,atomVelocity,atomCharge);
interscaleManager_.add_per_atom_quantity(atomic, "AtomicChargeVelocity");
}
return atomic;
}
//-----------------------------------------------------------------------------
//* m^a v'
//-----------------------------------------------------------------------------
PAQ * FieldManager::atomic_species_velocity()
{
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicSpeciesVelocity");
if (!atomic) {
PAQ * atomVelocity = atomic_fluctuating_velocity();
PAQ * atomSpecies = atomic_species_vector();
atomic = new SpeciesVelocity(atc_,atomVelocity,atomSpecies);
interscaleManager_.add_per_atom_quantity(atomic, "AtomicSpeciesVelocity");
}
return atomic;
}
//-----------------------------------------------------------------------------
//* [0 1 0 0 ] for type 2 atom
//-----------------------------------------------------------------------------
PAQ * FieldManager::atomic_species_vector()
{
PAQ * atomic = interscaleManager_.per_atom_quantity("AtomicSpeciesVector");
if (!atomic) {
atomic = new AtomTypeVector(atc_,atc_->type_list(),atc_->group_list());
interscaleManager_.add_per_atom_quantity(atomic,"AtomicSpeciesVector");
}
return atomic;
}
//-----------------------------------------------------------------------------
//* Prolonged coarse scale field
//-----------------------------------------------------------------------------
PAQ * FieldManager::prolonged_field(FieldName field)
{
PAQ * quantity = interscaleManager_.per_atom_quantity(field_to_prolongation_name(field));
if (!quantity) {
DENS_MAN * coarseQuantity = interscaleManager_.dense_matrix(field_to_string(field));
if (!coarseQuantity) coarseQuantity = nodal_atomic_field(field);
if (!coarseQuantity) throw ATC_Error("can not prolong quantity: " + field_to_string(field) + " no field registered");
if (atc_->kernel_on_the_fly()) {
quantity = new OnTheFlyShapeFunctionProlongation(atc_,
coarseQuantity,atc_->atom_coarsegraining_positions());
} else {
quantity = new FtaShapeFunctionProlongation(atc_,
coarseQuantity,atc_->interpolant());
}
interscaleManager_.add_per_atom_quantity(quantity,
field_to_prolongation_name(field));
}
return quantity;
}
}