#include "fix_atc.h"
#include <cstdio>
#include <cstring>
#include <sstream>
#include "fix_nve.h"
#include "atom.h"
#include "force.h"
#include "update.h"
#include "respa.h"
#include "error.h"
#include "neighbor.h"
#include "neigh_request.h"
#include "pointers.h"
#include "comm.h"
#include "group.h"
#include "ATC_Method.h"
#include "ATC_Transfer.h"
#include "ATC_TransferKernel.h"
#include "ATC_TransferPartitionOfUnity.h"
#include "ATC_CouplingEnergy.h"
#include "ATC_CouplingMomentum.h"
#include "ATC_CouplingMass.h"
#include "ATC_CouplingMomentumEnergy.h"
#include "LammpsInterface.h"
using namespace LAMMPS_NS;
using namespace FixConst;
using std::string;
#ifdef LAMMPS_BIGBIG
#error "The USER-ATC package is not compatible with -DLAMMPS_BIGBIG"
#endif
FixATC::FixATC(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg),
lammps_(lmp), atc_(NULL)
{
if (narg < 4 || narg > 5) lmp->error->all(FLERR,"Illegal fix atc command");
ATC::LammpsInterface::instance()->set_lammps(lmp);
int me = ATC::LammpsInterface::instance()->comm_rank();
string groupName(arg[1]);
int igroup = group->find(groupName.c_str());
int atomCount = group->count(igroup);
try {
if (strcmp(arg[3],"field")==0)
{
if (atomCount == 0) {
if (me==0) printf("ATC: can't construct transfer, no atoms in group \n");
throw;
}
if (narg < 5) {
if (me==0) printf("ATC: constructing shape function field estimate\n");
atc_ = new ATC::ATC_TransferPartitionOfUnity(groupName,
array_atom,
this);
}
else {
if (me==0) printf("ATC: constructing shape function field estimate with parameter file %s\n",arg[4]);
string matParamFile = arg[4];
atc_ = new ATC::ATC_TransferPartitionOfUnity(groupName,
array_atom, this,
matParamFile);
}
}
else if (strcmp(arg[3],"hardy")==0)
{
if (atomCount == 0) {
if (me==0) printf("ATC: Can't construct transfer, no atoms in group \n");
throw;
}
if (narg < 5) {
if (me==0) printf("ATC: constructing kernel field estimate\n");
atc_ = new ATC::ATC_TransferKernel(groupName,
array_atom,
this);
}
else {
if (me==0) printf("ATC: constructing kernel field estimate with parameter file %s\n",arg[4]);
string matParamFile = arg[4];
atc_ = new ATC::ATC_TransferKernel(groupName,
array_atom, this,
matParamFile);
}
}
else if (strcmp(arg[3],"thermal")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing thermal coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile);
}
else if (strcmp(arg[3],"two_temperature")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing two_temperature coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::TWO_TEMPERATURE);
}
else if (strcmp(arg[3],"drift_diffusion")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing drift_diffusion coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::DRIFT_DIFFUSION);
}
else if (strcmp(arg[3],"drift_diffusion-equilibrium")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing drift_diffusion-equilibrium coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::DRIFT_DIFFUSION_EQUILIBRIUM);
}
else if (strcmp(arg[3],"drift_diffusion-schrodinger")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing drift_diffusion-schrodinger coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::DRIFT_DIFFUSION_SCHRODINGER);
}
else if (strcmp(arg[3],"drift_diffusion-schrodinger-slice")==0)
{
string matParamFile = arg[4];
if (me==0) printf("Constructing ATC transfer (drift_diffusion-schrodinger-slice) with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::DRIFT_DIFFUSION_SCHRODINGER_SLICE);
}
else if (strcmp(arg[3],"convective_drift_diffusion")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing convective_drift_diffusion coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::CONVECTIVE_DRIFT_DIFFUSION);
}
else if (strcmp(arg[3],"convective_drift_diffusion-equilibrium")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing convective_drift_diffusion-equilibrium coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::CONVECTIVE_DRIFT_DIFFUSION_EQUILIBRIUM);
}
else if (strcmp(arg[3],"convective_drift_diffusion-schrodinger")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing convective_drift_diffusion-schrodinger coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingEnergy(groupName,
array_atom, this,
matParamFile, ATC::CONVECTIVE_DRIFT_DIFFUSION_SCHRODINGER);
}
else if (strcmp(arg[3],"elastic")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing elastic coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingMomentum(groupName,
array_atom, this,
matParamFile,
ATC::ELASTIC);
}
else if (strcmp(arg[3],"electrostatic")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing electrostatic mechanical coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingMomentum(groupName,
array_atom, this,
matParamFile,
ATC::ELASTIC,
ATC::ELECTROSTATIC);
}
else if (strcmp(arg[3],"electrostatic-equilibrium")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing equilibrium electrostatic coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingMomentum(groupName,
array_atom, this,
matParamFile,
ATC::ELASTIC,
ATC::ELECTROSTATIC_EQUILIBRIUM);
}
else if (strcmp(arg[3],"shear")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing viscous/shear coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingMomentum(groupName,
array_atom, this,
matParamFile,
ATC::SHEAR);
}
else if (strcmp(arg[3],"species")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing species diffusion coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingMass(groupName,
array_atom, this,
matParamFile);
}
else if (strcmp(arg[3],"species_electrostatic")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing electrostatic species coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingMass(groupName,
array_atom, this,
matParamFile, ATC::FEM_EFIELD);
}
else if (strcmp(arg[3],"thermo_elastic")==0)
{
string matParamFile = arg[4];
if (me==0) printf("ATC: constructing thermo-mechanical coupling with parameter file %s\n",arg[4]);
atc_ = new ATC::ATC_CouplingMomentumEnergy(groupName,
array_atom, this,
matParamFile);
}
else
{
lmp->error->all(FLERR,"Unknown physics type in ATC");
}
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
lmp->atom->add_callback(0);
restart_global = 0;
scalar_flag = atc_->scalar_flag();
vector_flag = atc_->vector_flag();
size_vector = atc_->size_vector();
global_freq = atc_->global_freq();
extscalar = atc_->extscalar();
extvector = atc_->extvector();
extlist = atc_->extlist();
thermo_energy = atc_->thermo_energy_flag();
peratom_flag = atc_->peratom_flag();
size_peratom_cols = atc_->size_peratom_cols();
peratom_freq = atc_->peratom_freq();
comm_forward = atc_->comm_forward();
nevery = 1;
}
FixATC::~FixATC()
{
if (lmp->atom) lmp->atom->delete_callback(id,0);
if (atc_) delete atc_;
}
int FixATC::setmask()
{
int mask = 0;
mask |= INITIAL_INTEGRATE;
mask |= POST_INTEGRATE;
mask |= FINAL_INTEGRATE;
mask |= PRE_EXCHANGE;
mask |= PRE_NEIGHBOR;
mask |= PRE_FORCE;
mask |= POST_FORCE;
mask |= MIN_PRE_EXCHANGE;
mask |= MIN_PRE_NEIGHBOR;
mask |= MIN_PRE_FORCE;
mask |= MIN_POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_RUN;
mask |= END_OF_STEP;
return mask;
}
int FixATC::modify_param(int narg, char** arg)
{
bool match;
try {
match = atc_->modify(narg,arg);
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
if (!match) return 0;
return narg;
}
void FixATC::init()
{
int irequest = neighbor->request(this,instance_me);
neighbor->requests[irequest]->pair = 0;
neighbor->requests[irequest]->fix = 1;
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;
atc_->init_computes();
}
void FixATC::min_setup(int vflag)
{
setup(vflag);
}
void FixATC::setup(int vflag)
{
comm->forward_comm_fix(this);
try {
atc_->initialize();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::pre_exchange()
{
try {
atc_->pre_exchange();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::setup_pre_exchange()
{
if (atc_->is_initialized()) {
try {
atc_->setup_pre_exchange();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
}
void FixATC::min_pre_exchange()
{
try {
atc_->pre_exchange();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
double FixATC::memory_usage()
{
double bytes = (double) atc_->memory_usage() * sizeof(double);
return bytes;
}
void FixATC::grow_arrays(int nmax)
{
atc_->grow_arrays(nmax);
}
void FixATC::copy_arrays(int i, int j, int delflag)
{
atc_->copy_arrays(i,j);
}
int FixATC::pack_exchange(int i, double * buf)
{
int num = atc_->pack_exchange(i,buf);
return num;
}
int FixATC::unpack_exchange(int nlocal, double * buf)
{
int num = atc_->unpack_exchange(nlocal,buf);
return num;
}
int FixATC::pack_forward_comm(int n, int *list, double *buf, int pbc_flag, int *pbc)
{
int num = atc_->pack_comm(n, list, buf, pbc_flag, pbc);
return num;
}
void FixATC::unpack_forward_comm(int n, int first, double *buf)
{
atc_->unpack_comm(n, first, buf);
}
int FixATC::pack_restart(int i, double *buf){
return 0;
}
void FixATC::unpack_restart(int nlocal, int nth){
}
int FixATC::maxsize_restart(){
return 0;
}
int FixATC::size_restart(int nlocal){
return 0;
}
void FixATC::write_restart(FILE *fp){
char ** args = new char*[2];
args[0] = new char[50];
args[1] = new char[50];
sprintf(args[0],"write_restart");
sprintf(args[1],"ATC.restart");
if (comm->me == 0) {
atc_->modify(2,args);
}
delete [] args[0];
delete [] args[1];
delete [] args;
}
void FixATC::restart(char *buf){
char ** args = new char*[2];
args[0] = new char[50];
args[1] = new char[50];
sprintf(args[0],"read_restart");
sprintf(args[1],"ATC.restart");
if (comm->me == 0) {
atc_->modify(2,args);
}
delete [] args[0];
delete [] args[1];
delete [] args;
}
void FixATC::initial_integrate(int vflag)
{
try {
atc_->pre_init_integrate();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
try {
atc_->init_integrate();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::post_integrate()
{
try {
atc_->post_init_integrate();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::final_integrate()
{
try {
atc_->pre_final_integrate();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
try {
atc_->final_integrate();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::end_of_step()
{
try {
atc_->post_final_integrate();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
try {
atc_->end_of_step();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::init_list(int id, NeighList *ptr) {
ATC::LammpsInterface::instance()->set_list(id,ptr);
}
void FixATC::pre_neighbor()
{
try {
atc_->pre_neighbor();
comm->forward_comm_fix(this);
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::pre_force(int vflag)
{
try {
atc_->pre_force();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::post_force(int vflag)
{
try {
atc_->post_force();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::post_run()
{
try {
atc_->finish();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::setup_pre_neighbor()
{
if (atc_->is_initialized()) {
try {
atc_->pre_neighbor();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
}
void FixATC::min_pre_force(int vflag)
{
try {
atc_->min_pre_force();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
void FixATC::min_post_force(int vflag)
{
try {
atc_->min_post_force();
}
catch (ATC::ATC_Error& atcError) {
ATC::LammpsInterface::instance()->print_msg(atcError.error_description());
throw;
}
}
double FixATC::compute_scalar()
{
return atc_->compute_scalar();
}
double FixATC::compute_vector(int n)
{
return atc_->compute_vector(n);
}
double FixATC::compute_array(int irow, int icol)
{
return atc_->compute_array(irow,icol);
}