diff --git a/src/ASPHERE/compute_temp_asphere.cpp b/src/ASPHERE/compute_temp_asphere.cpp index df9c22a228..7ce242e15a 100755 --- a/src/ASPHERE/compute_temp_asphere.cpp +++ b/src/ASPHERE/compute_temp_asphere.cpp @@ -29,6 +29,9 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 + /* ---------------------------------------------------------------------- */ ComputeTempAsphere::ComputeTempAsphere(LAMMPS *lmp, int narg, char **arg) : @@ -41,7 +44,8 @@ ComputeTempAsphere::ComputeTempAsphere(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; tempflag = 1; vector = new double[6]; @@ -110,6 +114,8 @@ void ComputeTempAsphere::recount() double ComputeTempAsphere::compute_scalar() { + invoked |= INVOKED_SCALAR; + double **v = atom->v; double **quat = atom->quat; double **angmom = atom->angmom; @@ -163,6 +169,8 @@ void ComputeTempAsphere::compute_vector() { int i; + invoked |= INVOKED_VECTOR; + double **v = atom->v; double **quat = atom->quat; double **angmom = atom->angmom; diff --git a/src/ASPHERE/fix_npt_asphere.cpp b/src/ASPHERE/fix_npt_asphere.cpp index 5e1e96cdb2..6fd81afe92 100755 --- a/src/ASPHERE/fix_npt_asphere.cpp +++ b/src/ASPHERE/fix_npt_asphere.cpp @@ -172,18 +172,16 @@ void FixNPTASphere::final_integrate() t_current = temperature->compute_scalar(); if (press_couple == 0) { - if (ptemperature) double ptmp = ptemperature->compute_scalar(); double tmp = pressure->compute_scalar(); } else { temperature->compute_vector(); - if (ptemperature) ptemperature->compute_vector(); pressure->compute_vector(); } couple(); // trigger virial computation on next timestep - pressure->add_step(update->ntimestep+1); + pressure->addstep(update->ntimestep+1); // update eta_dot diff --git a/src/CLASS2/bond_class2.cpp b/src/CLASS2/bond_class2.cpp index da744a2539..0f86c15ce6 100644 --- a/src/CLASS2/bond_class2.cpp +++ b/src/CLASS2/bond_class2.cpp @@ -198,12 +198,12 @@ void BondClass2::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondClass2::single(int type, double rsq, int i, int j, double &eng) +double BondClass2::single(int type, double rsq, int i, int j) { double r = sqrt(rsq); double dr = r - r0[type]; double dr2 = dr*dr; double dr3 = dr2*dr; double dr4 = dr3*dr; - eng = k2[type]*dr2 + k3[type]*dr3 + k4[type]*dr4; + return (k2[type]*dr2 + k3[type]*dr3 + k4[type]*dr4); } diff --git a/src/CLASS2/bond_class2.h b/src/CLASS2/bond_class2.h index 07b066431b..e98f58650f 100644 --- a/src/CLASS2/bond_class2.h +++ b/src/CLASS2/bond_class2.h @@ -28,7 +28,7 @@ class BondClass2 : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); private: double *r0,*k2,*k3,*k4; diff --git a/src/CLASS2/pair_lj_class2.cpp b/src/CLASS2/pair_lj_class2.cpp index bcce534b77..2c0770fbd6 100644 --- a/src/CLASS2/pair_lj_class2.cpp +++ b/src/CLASS2/pair_lj_class2.cpp @@ -354,9 +354,9 @@ void PairLJClass2::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJClass2::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairLJClass2::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,rinv,r3inv,r6inv,forcelj,philj; @@ -365,12 +365,9 @@ void PairLJClass2::single(int i, int j, int itype, int jtype, double rsq, r3inv = r2inv*rinv; r6inv = r3inv*r3inv; forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); - one.fforce = factor_lj*forcelj*r2inv; + fforce = factor_lj*forcelj*r2inv; - if (eflag) { - philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - one.eng_coul = 0.0; - } + philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - + offset[itype][jtype]; + return factor_lj*philj; } diff --git a/src/CLASS2/pair_lj_class2.h b/src/CLASS2/pair_lj_class2.h index ebe787bd14..33b05a9d92 100644 --- a/src/CLASS2/pair_lj_class2.h +++ b/src/CLASS2/pair_lj_class2.h @@ -30,7 +30,7 @@ class PairLJClass2 : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_global; diff --git a/src/CLASS2/pair_lj_class2_coul_cut.cpp b/src/CLASS2/pair_lj_class2_coul_cut.cpp index 24705e26c0..62ccda5082 100644 --- a/src/CLASS2/pair_lj_class2_coul_cut.cpp +++ b/src/CLASS2/pair_lj_class2_coul_cut.cpp @@ -412,9 +412,10 @@ void PairLJClass2CoulCut::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJClass2CoulCut::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, - double factor_lj, int eflag, One &one) +double PairLJClass2CoulCut::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,rinv,r3inv,r6inv,forcecoul,forcelj,phicoul,philj; @@ -428,17 +429,18 @@ void PairLJClass2CoulCut::single(int i, int j, int itype, int jtype, r6inv = r3inv*r3inv; forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); } else forcelj = 0.0; - one.fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; + fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; - if (eflag) { - if (rsq < cut_coulsq[itype][jtype]) { - phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); - one.eng_coul = factor_coul*phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq[itype][jtype]) { - philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + double eng = 0.0; + if (rsq < cut_coulsq[itype][jtype]) { + phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); + eng += factor_coul*phicoul; } + if (rsq < cut_ljsq[itype][jtype]) { + philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - + offset[itype][jtype]; + eng += factor_lj*philj; + } + + return eng; } diff --git a/src/CLASS2/pair_lj_class2_coul_cut.h b/src/CLASS2/pair_lj_class2_coul_cut.h index 20b4e66a9f..cac77257bc 100644 --- a/src/CLASS2/pair_lj_class2_coul_cut.h +++ b/src/CLASS2/pair_lj_class2_coul_cut.h @@ -31,7 +31,7 @@ class PairLJClass2CoulCut : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_lj_global,cut_coul_global; diff --git a/src/CLASS2/pair_lj_class2_coul_long.cpp b/src/CLASS2/pair_lj_class2_coul_long.cpp index 02a669c4e7..6412e2160c 100644 --- a/src/CLASS2/pair_lj_class2_coul_long.cpp +++ b/src/CLASS2/pair_lj_class2_coul_long.cpp @@ -423,9 +423,10 @@ void PairLJClass2CoulLong::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJClass2CoulLong::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, - double factor_lj, int eflag, One &one) +double PairLJClass2CoulLong::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r,rinv,r3inv,r6inv,grij,expm2,t,erfc,prefactor; double forcecoul,forcelj,phicoul,philj; @@ -447,20 +448,21 @@ void PairLJClass2CoulLong::single(int i, int j, int itype, int jtype, r6inv = r3inv*r3inv; forcelj = r6inv * (lj1[itype][jtype]*r3inv - lj2[itype][jtype]); } else forcelj = 0.0; - one.fforce = (forcecoul + factor_lj*forcelj) * r2inv; + fforce = (forcecoul + factor_lj*forcelj) * r2inv; - if (eflag) { - if (rsq < cut_coulsq) { - phicoul = prefactor*erfc; - if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; - one.eng_coul = phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq[itype][jtype]) { - philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + double eng = 0.0; + if (rsq < cut_coulsq) { + phicoul = prefactor*erfc; + if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; + eng += phicoul; } + if (rsq < cut_ljsq[itype][jtype]) { + philj = r6inv*(lj3[itype][jtype]*r3inv-lj4[itype][jtype]) - + offset[itype][jtype]; + eng += factor_lj*philj; + } + + return eng; } /* ---------------------------------------------------------------------- */ diff --git a/src/CLASS2/pair_lj_class2_coul_long.h b/src/CLASS2/pair_lj_class2_coul_long.h index 341e149395..73742ef337 100644 --- a/src/CLASS2/pair_lj_class2_coul_long.h +++ b/src/CLASS2/pair_lj_class2_coul_long.h @@ -31,7 +31,7 @@ class PairLJClass2CoulLong : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void *extract(char *); private: diff --git a/src/COLLOID/pair_colloid.cpp b/src/COLLOID/pair_colloid.cpp index 70e2fb45ec..59c6cc69d5 100644 --- a/src/COLLOID/pair_colloid.cpp +++ b/src/COLLOID/pair_colloid.cpp @@ -351,9 +351,8 @@ double PairColloid::init_one(int i, int j) offset[j][i] = offset[i][j] = 0.0; if (offset_flag) { - One one; - single(0,0,i,j,cutsq[i][j],0.0,1.0,1,one); - offset[j][i] = offset[i][j] = one.eng_vdwl; + double tmp; + offset[j][i] = offset[i][j] = single(0,0,i,j,cutsq[i][j],0.0,1.0,tmp); } return cut[i][j]; @@ -443,9 +442,9 @@ void PairColloid::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairColloid::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairColloid::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double K[9],h[4],g[4]; double r,r2inv,r6inv,forcelj,c1,c2,phi,fR,dUR,dUA; @@ -455,9 +454,9 @@ void PairColloid::single(int i, int j, int itype, int jtype, double rsq, r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); - one.fforce = factor_lj*forcelj*r2inv; - if (eflag) phi = r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) - - offset[itype][jtype]; + fforce = factor_lj*forcelj*r2inv; + phi = r6inv*(r6inv*lj3[itype][jtype]-lj4[itype][jtype]) - + offset[itype][jtype]; break; case SMALL_LARGE: @@ -470,13 +469,12 @@ void PairColloid::single(int i, int j, int itype, int jtype, double rsq, K[3] *= K[3]*K[3]; K[6] = K[3]*K[3]; fR = sigma3[itype][jtype]*a12[itype][jtype]*c2*K[1]/K[3]; - one.fforce = 4.0/15.0*r*fR*factor_lj * + fforce = 4.0/15.0*r*fR*factor_lj * (2.0*(K[1]+K[2])*(K[1]*(5.0*K[1]+22.0*K[2])+5.0*K[4]) * sigma6[itype][jtype]/K[6] - 5.0)/K[0]; - if (eflag) - phi = 2.0/9.0*fR * - (1.0-(K[1]*(K[1]*(K[1]/3.0+3.0*K[2])+4.2*K[4])+K[2]*K[4]) * - sigma6[itype][jtype]/K[6]) - offset[itype][jtype]; + phi = 2.0/9.0*fR * + (1.0-(K[1]*(K[1]*(K[1]/3.0+3.0*K[2])+4.2*K[4])+K[2]*K[4]) * + sigma6[itype][jtype]/K[6]) - offset[itype][jtype]; break; case LARGE_LARGE: @@ -510,16 +508,11 @@ void PairColloid::single(int i, int j, int itype, int jtype, double rsq, dUR = phi/r + 5.0*fR*(g[0]+g[1]-g[2]-g[3]); dUA = -a12[itype][jtype]/3.0*r*((2.0*K[0]*K[7]+1.0)*K[7] + (2.0*K[0]*K[8]-1.0)*K[8]); - one.fforce = factor_lj*(dUR+dUA)/r; - - if (eflag) - phi += a12[itype][jtype]/6.0*(2.0*K[0]*(K[7]+K[8])-log(K[8]/K[7])) - - offset[itype][jtype]; + fforce = factor_lj*(dUR+dUA)/r; + phi += a12[itype][jtype]/6.0*(2.0*K[0]*(K[7]+K[8])-log(K[8]/K[7])) - + offset[itype][jtype]; break; } - if (eflag) { - one.eng_vdwl = factor_lj*phi; - one.eng_coul = 0.0; - } + return factor_lj*phi; } diff --git a/src/COLLOID/pair_colloid.h b/src/COLLOID/pair_colloid.h index ab89a3e728..87e10ef861 100644 --- a/src/COLLOID/pair_colloid.h +++ b/src/COLLOID/pair_colloid.h @@ -30,7 +30,7 @@ class PairColloid : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_global; diff --git a/src/DIPOLE/compute_temp_dipole.cpp b/src/DIPOLE/compute_temp_dipole.cpp index dac8f11671..7c06106fa5 100644 --- a/src/DIPOLE/compute_temp_dipole.cpp +++ b/src/DIPOLE/compute_temp_dipole.cpp @@ -23,9 +23,9 @@ using namespace LAMMPS_NS; -// moment of inertia for a sphere - -#define INERTIA 0.4 +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 +#define INERTIA 0.4 // moment of inertia for a sphere /* ---------------------------------------------------------------------- */ @@ -39,7 +39,8 @@ ComputeTempDipole::ComputeTempDipole(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; tempflag = 1; vector = new double[6]; @@ -87,6 +88,8 @@ void ComputeTempDipole::recount() double ComputeTempDipole::compute_scalar() { + invoked |= INVOKED_SCALAR; + double **v = atom->v; double *mass = atom->mass; double **omega = atom->omega; @@ -116,6 +119,8 @@ void ComputeTempDipole::compute_vector() { int i; + invoked |= INVOKED_VECTOR; + double **v = atom->v; double *mass = atom->mass; double **omega = atom->omega; diff --git a/src/DPD/pair_dpd.cpp b/src/DPD/pair_dpd.cpp index 5a0dba23e1..8548fa4dc1 100644 --- a/src/DPD/pair_dpd.cpp +++ b/src/DPD/pair_dpd.cpp @@ -260,7 +260,7 @@ void PairDPD::init_style() // using different random numbers if (force->newton_pair == 0 && comm->me == 0) error->warning( - "DPD potential needs newton pair on for momentum conservation"); + "Pair style dpd needs newton pair on for momentum conservation"); int irequest = neighbor->request(this); } @@ -370,27 +370,21 @@ void PairDPD::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairDPD::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_dpd, int eflag, - One &one) +double PairDPD::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_dpd, double &fforce) { double r,rinv,wd,phi; r = sqrt(rsq); if (r < EPSILON) { - one.fforce = 0.0; - if (eflag) one.eng_vdwl = one.eng_coul = 0.0; - return; + fforce = 0.0; + return 0.0; } rinv = 1.0/r; wd = 1.0 - r/cut[itype][jtype]; - - one.fforce = a0[itype][jtype]*wd * factor_dpd*rinv; + fforce = a0[itype][jtype]*wd * factor_dpd*rinv; - if (eflag) { - phi = a0[itype][jtype] * r * (1.0 - 0.5*r/cut[itype][jtype]); - one.eng_vdwl = factor_dpd*phi; - one.eng_coul = 0.0; - } + phi = a0[itype][jtype] * r * (1.0 - 0.5*r/cut[itype][jtype]); + return factor_dpd*phi; } diff --git a/src/DPD/pair_dpd.h b/src/DPD/pair_dpd.h index 367977bfc4..af3d64ffae 100644 --- a/src/DPD/pair_dpd.h +++ b/src/DPD/pair_dpd.h @@ -31,7 +31,7 @@ class PairDPD : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_global,temperature; diff --git a/src/KSPACE/pair_buck_coul_long.cpp b/src/KSPACE/pair_buck_coul_long.cpp index e76a853921..67839465a0 100644 --- a/src/KSPACE/pair_buck_coul_long.cpp +++ b/src/KSPACE/pair_buck_coul_long.cpp @@ -394,9 +394,10 @@ void PairBuckCoulLong::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairBuckCoulLong::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, double factor_lj, - int eflag, One &one) +double PairBuckCoulLong::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,r,rexp,grij,expm2,t,erfc,prefactor; double forcecoul,forcebuck,phicoul,phibuck; @@ -418,20 +419,20 @@ void PairBuckCoulLong::single(int i, int j, int itype, int jtype, rexp = exp(-r*rhoinv[itype][jtype]); forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv; } else forcebuck = 0.0; - one.fforce = (forcecoul + factor_lj*forcebuck) * r2inv; + fforce = (forcecoul + factor_lj*forcebuck) * r2inv; - if (eflag) { - if (rsq < cut_coulsq) { - phicoul = prefactor*erfc; - if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; - one.eng_coul = phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq[itype][jtype]) { - phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*phibuck; - } else one.eng_vdwl = 0.0; + double eng = 0.0; + if (rsq < cut_coulsq) { + phicoul = prefactor*erfc; + if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; + eng += phicoul; } + if (rsq < cut_ljsq[itype][jtype]) { + phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv - + offset[itype][jtype]; + eng += factor_lj*phibuck; + } + return eng; } /* ---------------------------------------------------------------------- */ diff --git a/src/KSPACE/pair_buck_coul_long.h b/src/KSPACE/pair_buck_coul_long.h index 87c7dc3e08..f177bc20ce 100644 --- a/src/KSPACE/pair_buck_coul_long.h +++ b/src/KSPACE/pair_buck_coul_long.h @@ -31,7 +31,7 @@ class PairBuckCoulLong : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void *extract(char *); private: diff --git a/src/KSPACE/pair_coul_long.cpp b/src/KSPACE/pair_coul_long.cpp index f1099d1866..e50eba0474 100644 --- a/src/KSPACE/pair_coul_long.cpp +++ b/src/KSPACE/pair_coul_long.cpp @@ -512,10 +512,10 @@ void PairCoulLong::free_tables() /* ---------------------------------------------------------------------- */ -void PairCoulLong::single(int i, int j, int itype, int jtype, - double rsq, - double factor_coul, double factor_lj, - int eflag, One &one) +double PairCoulLong::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r,grij,expm2,t,erfc,prefactor; double fraction,table,forcecoul,phicoul; @@ -545,19 +545,17 @@ void PairCoulLong::single(int i, int j, int itype, int jtype, forcecoul -= (1.0-factor_coul)*prefactor; } } - one.fforce = forcecoul * r2inv; + fforce = forcecoul * r2inv; - if (eflag) { - if (!ncoultablebits || rsq <= tabinnersq) - phicoul = prefactor*erfc; - else { - table = etable[itable] + fraction*detable[itable]; - phicoul = atom->q[i]*atom->q[j] * table; - } - if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; - one.eng_coul = phicoul; - one.eng_vdwl = 0.0; + if (!ncoultablebits || rsq <= tabinnersq) + phicoul = prefactor*erfc; + else { + table = etable[itable] + fraction*detable[itable]; + phicoul = atom->q[i]*atom->q[j] * table; } + if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; + + return phicoul; } /* ---------------------------------------------------------------------- */ diff --git a/src/KSPACE/pair_coul_long.h b/src/KSPACE/pair_coul_long.h index 60accab7d1..66c76fe7c9 100644 --- a/src/KSPACE/pair_coul_long.h +++ b/src/KSPACE/pair_coul_long.h @@ -31,7 +31,7 @@ class PairCoulLong : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void *extract(char *); private: diff --git a/src/KSPACE/pair_lj_charmm_coul_long.cpp b/src/KSPACE/pair_lj_charmm_coul_long.cpp index f874fc93d4..45698ff9c3 100644 --- a/src/KSPACE/pair_lj_charmm_coul_long.cpp +++ b/src/KSPACE/pair_lj_charmm_coul_long.cpp @@ -1127,10 +1127,10 @@ void PairLJCharmmCoulLong::free_tables() /* ---------------------------------------------------------------------- */ -void PairLJCharmmCoulLong::single(int i, int j, int itype, int jtype, - double rsq, - double factor_coul, double factor_lj, - int eflag, One &one) +double PairLJCharmmCoulLong::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,r,grij,expm2,t,erfc,prefactor; double switch1,switch2,fraction,table,forcecoul,forcelj,phicoul,philj; @@ -1174,29 +1174,31 @@ void PairLJCharmmCoulLong::single(int i, int j, int itype, int jtype, forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; - one.fforce = (forcecoul + factor_lj*forcelj) * r2inv; + fforce = (forcecoul + factor_lj*forcelj) * r2inv; - if (eflag) { - if (rsq < cut_coulsq) { - if (!ncoultablebits || rsq <= tabinnersq) - phicoul = prefactor*erfc; - else { - table = etable[itable] + fraction*detable[itable]; - phicoul = atom->q[i]*atom->q[j] * table; - } - if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; - one.eng_coul = phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); - if (rsq > cut_lj_innersq) { - switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * - (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; - philj *= switch1; - } - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + double eng = 0.0; + if (rsq < cut_coulsq) { + if (!ncoultablebits || rsq <= tabinnersq) + phicoul = prefactor*erfc; + else { + table = etable[itable] + fraction*detable[itable]; + phicoul = atom->q[i]*atom->q[j] * table; + } + if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; + eng += phicoul; } + + if (rsq < cut_ljsq) { + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); + if (rsq > cut_lj_innersq) { + switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * + (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; + philj *= switch1; + } + eng += factor_lj*philj; + } + + return eng; } /* ---------------------------------------------------------------------- */ diff --git a/src/KSPACE/pair_lj_charmm_coul_long.h b/src/KSPACE/pair_lj_charmm_coul_long.h index db094d9eda..02d7aadc87 100644 --- a/src/KSPACE/pair_lj_charmm_coul_long.h +++ b/src/KSPACE/pair_lj_charmm_coul_long.h @@ -32,7 +32,7 @@ class PairLJCharmmCoulLong : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); diff --git a/src/KSPACE/pair_lj_cut_coul_long.cpp b/src/KSPACE/pair_lj_cut_coul_long.cpp index 1ea3127c4c..4e9b3373b4 100644 --- a/src/KSPACE/pair_lj_cut_coul_long.cpp +++ b/src/KSPACE/pair_lj_cut_coul_long.cpp @@ -1080,10 +1080,10 @@ void PairLJCutCoulLong::free_tables() /* ---------------------------------------------------------------------- */ -void PairLJCutCoulLong::single(int i, int j, int itype, int jtype, - double rsq, - double factor_coul, double factor_lj, - int eflag, One &one) +double PairLJCutCoulLong::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,r,grij,expm2,t,erfc,prefactor; double fraction,table,forcecoul,forcelj,phicoul,philj; @@ -1115,29 +1115,33 @@ void PairLJCutCoulLong::single(int i, int j, int itype, int jtype, } } } else forcecoul = 0.0; + if (rsq < cut_ljsq[itype][jtype]) { r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; - one.fforce = (forcecoul + factor_lj*forcelj) * r2inv; - - if (eflag) { - if (rsq < cut_coulsq) { - if (!ncoultablebits || rsq <= tabinnersq) - phicoul = prefactor*erfc; - else { - table = etable[itable] + fraction*detable[itable]; - phicoul = atom->q[i]*atom->q[j] * table; - } - if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; - one.eng_coul = phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq[itype][jtype]) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + + fforce = (forcecoul + factor_lj*forcelj) * r2inv; + + double eng = 0.0; + if (rsq < cut_coulsq) { + if (!ncoultablebits || rsq <= tabinnersq) + phicoul = prefactor*erfc; + else { + table = etable[itable] + fraction*detable[itable]; + phicoul = atom->q[i]*atom->q[j] * table; + } + if (factor_coul < 1.0) phicoul -= (1.0-factor_coul)*prefactor; + eng += phicoul; } + + if (rsq < cut_ljsq[itype][jtype]) { + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - + offset[itype][jtype]; + eng += factor_lj*philj; + } + + return eng; } /* ---------------------------------------------------------------------- */ diff --git a/src/KSPACE/pair_lj_cut_coul_long.h b/src/KSPACE/pair_lj_cut_coul_long.h index 415bcd5e88..b241d7d895 100644 --- a/src/KSPACE/pair_lj_cut_coul_long.h +++ b/src/KSPACE/pair_lj_cut_coul_long.h @@ -32,7 +32,7 @@ class PairLJCutCoulLong : public Pair { void read_restart(FILE *); virtual void write_restart_settings(FILE *); virtual void read_restart_settings(FILE *); - virtual void single(int, int, int, int, double, double, double, int, One &); + virtual double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); diff --git a/src/MANYBODY/pair_airebo.h b/src/MANYBODY/pair_airebo.h index c8e2774443..1de72a576c 100644 --- a/src/MANYBODY/pair_airebo.h +++ b/src/MANYBODY/pair_airebo.h @@ -21,7 +21,7 @@ namespace LAMMPS_NS { class PairAIREBO : public Pair { public: PairAIREBO(class LAMMPS *); - virtual ~PairAIREBO(); + ~PairAIREBO(); void compute(int, int); void settings(int, char **); void coeff(int, char **); @@ -31,7 +31,6 @@ class PairAIREBO : public Pair { void read_restart(FILE *) {} void write_restart_settings(FILE *) {} void read_restart_settings(FILE *) {} - void single(int, int, int, int, double, double, double, int, One &) {} private: int me; diff --git a/src/MANYBODY/pair_eam.cpp b/src/MANYBODY/pair_eam.cpp index 5c48c9f982..b12b922baf 100644 --- a/src/MANYBODY/pair_eam.cpp +++ b/src/MANYBODY/pair_eam.cpp @@ -764,9 +764,9 @@ void PairEAM::grab(FILE *fp, int n, double *list) /* ---------------------------------------------------------------------- */ -void PairEAM::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, double factor_lj, - int eflag, One &one) +double PairEAM::single(int i, int j, int itype, int jtype, + double rsq, double factor_coul, double factor_lj, + double &fforce) { int m; double r,p,rhoip,rhojp,z2,z2p,recip,phi,phip,psip; @@ -791,12 +791,9 @@ void PairEAM::single(int i, int j, int itype, int jtype, phi = z2*recip; phip = z2p*recip - phi*recip; psip = fp[i]*rhojp + fp[j]*rhoip + phip; - one.fforce = -psip*recip; + fforce = -psip*recip; - if (eflag) { - one.eng_vdwl = phi; - one.eng_coul = 0.0; - } + return phi; } /* ---------------------------------------------------------------------- */ diff --git a/src/MANYBODY/pair_eam.h b/src/MANYBODY/pair_eam.h index 3d88bfd86d..8bcf8ed04d 100644 --- a/src/MANYBODY/pair_eam.h +++ b/src/MANYBODY/pair_eam.h @@ -27,7 +27,7 @@ class PairEAM : public Pair { virtual void coeff(int, char **); void init_style(); double init_one(int, int); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); int pack_comm(int, int *, double *, int, int *); void unpack_comm(int, int, double *); diff --git a/src/MOLECULE/angle_hybrid.cpp b/src/MOLECULE/angle_hybrid.cpp index 307e1355be..a335259d64 100644 --- a/src/MOLECULE/angle_hybrid.cpp +++ b/src/MOLECULE/angle_hybrid.cpp @@ -259,9 +259,8 @@ void AngleHybrid::read_restart(FILE *fp) double AngleHybrid::single(int type, int i1, int i2, int i3) { - if (styles[map[type]]) - return styles[map[type]]->single(type,i1,i2,i3); - else return 0.0; + if (styles[map[type]]) return styles[map[type]]->single(type,i1,i2,i3); + return 0.0; } /* ---------------------------------------------------------------------- diff --git a/src/MOLECULE/bond_fene.cpp b/src/MOLECULE/bond_fene.cpp index 9bf82538c1..11c3b54b53 100644 --- a/src/MOLECULE/bond_fene.cpp +++ b/src/MOLECULE/bond_fene.cpp @@ -217,7 +217,7 @@ void BondFENE::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondFENE::single(int type, double rsq, int i, int j, double &eng) +double BondFENE::single(int type, double rsq, int i, int j) { double r0sq = r0[type] * r0[type]; double rlogarg = 1.0 - rsq/r0sq; @@ -234,11 +234,13 @@ void BondFENE::single(int type, double rsq, int i, int j, double &eng) rlogarg = 0.1; } - eng = -0.5 * k[type]*r0sq*log(rlogarg); + double eng = -0.5 * k[type]*r0sq*log(rlogarg); if (rsq < TWO_1_3*sigma[type]*sigma[type]) { double sr2,sr6; sr2 = sigma[type]*sigma[type]/rsq; sr6 = sr2*sr2*sr2; eng += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type]; } + + return eng; } diff --git a/src/MOLECULE/bond_fene.h b/src/MOLECULE/bond_fene.h index 68d234ac0e..902e84e8e9 100644 --- a/src/MOLECULE/bond_fene.h +++ b/src/MOLECULE/bond_fene.h @@ -28,7 +28,7 @@ class BondFENE : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); private: double TWO_1_3; diff --git a/src/MOLECULE/bond_fene_expand.cpp b/src/MOLECULE/bond_fene_expand.cpp index 4ddef18ab1..05f3fc1c8a 100644 --- a/src/MOLECULE/bond_fene_expand.cpp +++ b/src/MOLECULE/bond_fene_expand.cpp @@ -228,7 +228,7 @@ void BondFENEExpand::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondFENEExpand::single(int type, double rsq, int i, int j, double &eng) +double BondFENEExpand::single(int type, double rsq, int i, int j) { double r = sqrt(rsq); double rshift = r - shift[type]; @@ -248,11 +248,13 @@ void BondFENEExpand::single(int type, double rsq, int i, int j, double &eng) rlogarg = 0.1; } - eng = -0.5 * k[type]*r0sq*log(rlogarg); + double eng = -0.5 * k[type]*r0sq*log(rlogarg); if (rshiftsq < TWO_1_3*sigma[type]*sigma[type]) { double sr2,sr6; sr2 = sigma[type]*sigma[type]/rshiftsq; sr6 = sr2*sr2*sr2; eng += 4.0*epsilon[type]*sr6*(sr6-1.0) + epsilon[type]; } + + return eng; } diff --git a/src/MOLECULE/bond_fene_expand.h b/src/MOLECULE/bond_fene_expand.h index 6cf62e5d29..515e95c617 100644 --- a/src/MOLECULE/bond_fene_expand.h +++ b/src/MOLECULE/bond_fene_expand.h @@ -28,7 +28,7 @@ class BondFENEExpand : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); private: double TWO_1_3; diff --git a/src/MOLECULE/bond_harmonic.cpp b/src/MOLECULE/bond_harmonic.cpp index ade063db4b..1921f5b3a9 100644 --- a/src/MOLECULE/bond_harmonic.cpp +++ b/src/MOLECULE/bond_harmonic.cpp @@ -177,10 +177,10 @@ void BondHarmonic::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondHarmonic::single(int type, double rsq, int i, int j, double &eng) +double BondHarmonic::single(int type, double rsq, int i, int j) { double r = sqrt(rsq); double dr = r - r0[type]; double rk = k[type] * dr; - eng = rk*dr; + return rk*dr; } diff --git a/src/MOLECULE/bond_harmonic.h b/src/MOLECULE/bond_harmonic.h index 361493cfc7..14bd8c7794 100644 --- a/src/MOLECULE/bond_harmonic.h +++ b/src/MOLECULE/bond_harmonic.h @@ -28,7 +28,7 @@ class BondHarmonic : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); private: double *k,*r0; diff --git a/src/MOLECULE/bond_hybrid.cpp b/src/MOLECULE/bond_hybrid.cpp index da3de7f21a..03a63ef1f6 100644 --- a/src/MOLECULE/bond_hybrid.cpp +++ b/src/MOLECULE/bond_hybrid.cpp @@ -263,9 +263,10 @@ void BondHybrid::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondHybrid::single(int type, double rsq, int i, int j, double &eng) +double BondHybrid::single(int type, double rsq, int i, int j) { - if (styles[map[type]]) styles[map[type]]->single(type,rsq,i,j,eng); + if (styles[map[type]]) return styles[map[type]]->single(type,rsq,i,j); + return 0.0; } /* ---------------------------------------------------------------------- diff --git a/src/MOLECULE/bond_morse.cpp b/src/MOLECULE/bond_morse.cpp index c491962e00..9accf9a89c 100644 --- a/src/MOLECULE/bond_morse.cpp +++ b/src/MOLECULE/bond_morse.cpp @@ -187,10 +187,10 @@ void BondMorse::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondMorse::single(int type, double rsq, int i, int j, double &eng) +double BondMorse::single(int type, double rsq, int i, int j) { double r = sqrt(rsq); double dr = r - r0[type]; double ralpha = exp(-alpha[type]*dr); - eng = d0[type]*(1-ralpha)*(1-ralpha); + return d0[type]*(1-ralpha)*(1-ralpha); } diff --git a/src/MOLECULE/bond_morse.h b/src/MOLECULE/bond_morse.h index 3d5625c3b8..bcccceb146 100644 --- a/src/MOLECULE/bond_morse.h +++ b/src/MOLECULE/bond_morse.h @@ -28,7 +28,7 @@ class BondMorse : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); private: double *d0,*alpha,*r0; diff --git a/src/MOLECULE/bond_nonlinear.cpp b/src/MOLECULE/bond_nonlinear.cpp index 2979ba0b28..b6843333c6 100644 --- a/src/MOLECULE/bond_nonlinear.cpp +++ b/src/MOLECULE/bond_nonlinear.cpp @@ -182,12 +182,12 @@ void BondNonlinear::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondNonlinear::single(int type, double rsq, int i, int j, double &eng) +double BondNonlinear::single(int type, double rsq, int i, int j) { double r = sqrt(rsq); double dr = r - r0[type]; double drsq = dr*dr; double lamdasq = lamda[type]*lamda[type]; double denom = lamdasq - drsq; - eng = epsilon[type] * drsq / denom; + return epsilon[type] * drsq / denom; } diff --git a/src/MOLECULE/bond_nonlinear.h b/src/MOLECULE/bond_nonlinear.h index 9238d1ae3f..24686191b2 100644 --- a/src/MOLECULE/bond_nonlinear.h +++ b/src/MOLECULE/bond_nonlinear.h @@ -28,7 +28,7 @@ class BondNonlinear : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); private: double *epsilon,*r0,*lamda; diff --git a/src/MOLECULE/bond_quartic.cpp b/src/MOLECULE/bond_quartic.cpp index e1072baf42..75130c8383 100755 --- a/src/MOLECULE/bond_quartic.cpp +++ b/src/MOLECULE/bond_quartic.cpp @@ -58,7 +58,6 @@ void BondQuartic::compute(int eflag, int vflag) int i1,i2,n,m,type,itype,jtype; double delx,dely,delz,ebond,fbond,evdwl,fpair; double r,rsq,dr,r2,ra,rb,sr2,sr6; - Pair::One one; ebond = evdwl = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); @@ -158,9 +157,8 @@ void BondQuartic::compute(int eflag, int vflag) jtype = atom->type[i2]; if (rsq < cutsq[itype][jtype]) { - force->pair->single(i1,i2,itype,jtype,rsq,1.0,1.0,eflag,one); - fpair = -one.fforce; - if (eflag) evdwl = -(one.eng_vdwl + one.eng_coul); + evdwl = -force->pair->single(i1,i2,itype,jtype,rsq,1.0,1.0,fpair); + fpair = -fpair; if (newton_bond || i1 < nlocal) { f[i1][0] += delx*fpair; @@ -299,12 +297,12 @@ void BondQuartic::read_restart(FILE *fp) /* ---------------------------------------------------------------------- */ -void BondQuartic::single(int type, double rsq, int i, int j, double &eng) +double BondQuartic::single(int type, double rsq, int i, int j) { double r,dr,r2,ra,rb,sr2,sr6; - eng = 0.0; - if (type <= 0) return; + if (type <= 0) return 0.0; + double eng = 0.0; // subtract out pairwise contribution from 2 atoms via pair->single() // required since special_bond = 1,1,1 @@ -313,9 +311,8 @@ void BondQuartic::single(int type, double rsq, int i, int j, double &eng) int jtype = atom->type[j]; if (rsq < force->pair->cutsq[itype][jtype]) { - Pair::One one; - force->pair->single(i,j,itype,jtype,rsq,1.0,1.0,1,one); - eng = -one.eng_coul - one.eng_vdwl; + double tmp; + eng = -force->pair->single(i,j,itype,jtype,rsq,1.0,1.0,tmp); } // quartic bond @@ -334,4 +331,6 @@ void BondQuartic::single(int type, double rsq, int i, int j, double &eng) sr6 = sr2*sr2*sr2; eng += 4.0*sr6*(sr6-1.0) + 1.0; } + + return eng; } diff --git a/src/MOLECULE/bond_quartic.h b/src/MOLECULE/bond_quartic.h index 5fae223787..e25ab1eb09 100644 --- a/src/MOLECULE/bond_quartic.h +++ b/src/MOLECULE/bond_quartic.h @@ -29,7 +29,7 @@ class BondQuartic : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); private: double TWO_1_3; diff --git a/src/MOLECULE/improper_harmonic.cpp b/src/MOLECULE/improper_harmonic.cpp index de49668f7d..700da09340 100644 --- a/src/MOLECULE/improper_harmonic.cpp +++ b/src/MOLECULE/improper_harmonic.cpp @@ -162,9 +162,9 @@ void ImproperHarmonic::compute(int eflag, int vflag) sy2 = a22*vb2y + a23*vb3y + a12*vb1y; sz2 = a22*vb2z + a23*vb3z + a12*vb1z; - f1[0] = a12*vb2x + a13*vb3x + a11*vb1x; - f1[1] = a12*vb2y + a13*vb3y + a11*vb1y; - f1[2] = a12*vb2z + a13*vb3z + a11*vb1z; + f1[0] = a12*vb2x + a13*vb3x + a11*vb1x; + f1[1] = a12*vb2y + a13*vb3y + a11*vb1y; + f1[2] = a12*vb2z + a13*vb3z + a11*vb1z; f2[0] = -sx2 - f1[0]; f2[1] = -sy2 - f1[1]; diff --git a/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp b/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp index b1f9dff6c2..e926be62c3 100644 --- a/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp +++ b/src/MOLECULE/pair_lj_charmm_coul_charmm.cpp @@ -436,10 +436,10 @@ void PairLJCharmmCoulCharmm::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJCharmmCoulCharmm::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, - double factor_lj, - int eflag, One &one) +double PairLJCharmmCoulCharmm::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,switch1,switch2,forcecoul,forcelj,phicoul,philj; @@ -466,29 +466,30 @@ void PairLJCharmmCoulCharmm::single(int i, int j, int itype, int jtype, forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; - one.fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; - - if (eflag) { - if (rsq < cut_coulsq) { - phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); - if (rsq > cut_coul_innersq) { - switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) * - (cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / - denom_coul; - phicoul *= switch1; - } - one.eng_coul = factor_coul*phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); - if (rsq > cut_lj_innersq) { - switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * - (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; - philj *= switch1; - } - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; + + double eng = 0.0; + if (rsq < cut_coulsq) { + phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); + if (rsq > cut_coul_innersq) { + switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) * + (cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / + denom_coul; + phicoul *= switch1; + } + eng += factor_coul*phicoul; } + if (rsq < cut_ljsq) { + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); + if (rsq > cut_lj_innersq) { + switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * + (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; + philj *= switch1; + } + eng += factor_lj*philj; + } + + return eng; } /* ---------------------------------------------------------------------- */ diff --git a/src/MOLECULE/pair_lj_charmm_coul_charmm.h b/src/MOLECULE/pair_lj_charmm_coul_charmm.h index 6eb59a49e5..e23766b414 100644 --- a/src/MOLECULE/pair_lj_charmm_coul_charmm.h +++ b/src/MOLECULE/pair_lj_charmm_coul_charmm.h @@ -31,7 +31,7 @@ class PairLJCharmmCoulCharmm : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - virtual void single(int, int, int, int, double, double, double, int, One &); + virtual double single(int, int, int, int, double, double, double, double &); virtual void *extract(char *); protected: diff --git a/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.cpp b/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.cpp index 71dc72f087..21812b03c7 100644 --- a/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.cpp +++ b/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.cpp @@ -157,10 +157,12 @@ void PairLJCharmmCoulCharmmImplicit::compute(int eflag, int vflag) /* ---------------------------------------------------------------------- */ -void PairLJCharmmCoulCharmmImplicit::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, - double factor_lj, - int eflag, One &one) +double PairLJCharmmCoulCharmmImplicit::single(int i, int j, + int itype, int jtype, + double rsq, + double factor_coul, + double factor_lj, + double &fforce) { double r2inv,r6inv,switch1,switch2,forcecoul,forcelj,phicoul,philj; @@ -187,29 +189,30 @@ void PairLJCharmmCoulCharmmImplicit::single(int i, int j, int itype, int jtype, forcelj = forcelj*switch1 + philj*switch2; } } else forcelj = 0.0; - one.fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; - - if (eflag) { - if (rsq < cut_coulsq) { - phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*r2inv; - if (rsq > cut_coul_innersq) { - switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) * - (cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / - denom_coul; - phicoul *= switch1; - } - one.eng_coul = factor_coul*phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); - if (rsq > cut_lj_innersq) { - switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * - (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; - philj *= switch1; - } - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; + + double eng = 0.0; + if (rsq < cut_coulsq) { + phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*r2inv; + if (rsq > cut_coul_innersq) { + switch1 = (cut_coulsq-rsq) * (cut_coulsq-rsq) * + (cut_coulsq + 2.0*rsq - 3.0*cut_coul_innersq) / + denom_coul; + phicoul *= switch1; + } + eng += factor_coul*phicoul; } + if (rsq < cut_ljsq) { + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]); + if (rsq > cut_lj_innersq) { + switch1 = (cut_ljsq-rsq) * (cut_ljsq-rsq) * + (cut_ljsq + 2.0*rsq - 3.0*cut_lj_innersq) / denom_lj; + philj *= switch1; + } + eng += factor_lj*philj; + } + + return eng; } /* ---------------------------------------------------------------------- */ diff --git a/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.h b/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.h index 45a95982b8..910e0c9a19 100644 --- a/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.h +++ b/src/MOLECULE/pair_lj_charmm_coul_charmm_implicit.h @@ -22,7 +22,7 @@ class PairLJCharmmCoulCharmmImplicit : public PairLJCharmmCoulCharmm { public: PairLJCharmmCoulCharmmImplicit(class LAMMPS *); void compute(int, int); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void *extract(char *); }; diff --git a/src/USER-ACKLAND/compute_ackland_atom.cpp b/src/USER-ACKLAND/compute_ackland_atom.cpp index 17d4c6c35c..80db2b40b9 100644 --- a/src/USER-ACKLAND/compute_ackland_atom.cpp +++ b/src/USER-ACKLAND/compute_ackland_atom.cpp @@ -34,6 +34,7 @@ using namespace LAMMPS_NS; enum{UNKNOWN,BCC,FCC,HCP,ICO}; +#define INVOKED_PERATOM 4 /* ---------------------------------------------------------------------- */ @@ -93,6 +94,7 @@ void ComputeAcklandAtom::init_list(int id, NeighList *ptr) } /* ---------------------------------------------------------------------- */ + void ComputeAcklandAtom::compute_peratom() { int i,j,ii,jj,k,n,inum,jnum; @@ -100,6 +102,8 @@ void ComputeAcklandAtom::compute_peratom() int *ilist,*jlist,*numneigh,**firstneigh; int chi[8]; + invoked |= INVOKED_PERATOM; + // grow structure array if necessary if (atom->nlocal > nmax) { diff --git a/src/USER-EWALDN/pair_buck_coul.cpp b/src/USER-EWALDN/pair_buck_coul.cpp index 4396ecf832..309be85f1b 100644 --- a/src/USER-EWALDN/pair_buck_coul.cpp +++ b/src/USER-EWALDN/pair_buck_coul.cpp @@ -1116,24 +1116,24 @@ void PairBuckCoul::free_tables() /* ---------------------------------------------------------------------- */ -void PairBuckCoul::single(int i, int j, int itype, int jtype, - double rsq, - double factor_coul, double factor_buck, - int eflag, One &one) +double PairBuckCoul::single(int i, int j, int itype, int jtype, + double rsq, double factor_coul, double factor_buck, + double &fforce) { double f, r, r2inv, r6inv, force_coul, force_buck; double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2, *q = atom->q; r = sqrt(rsq); r2inv = 1.0/rsq; - one.eng_coul = 0.0; + double eng = 0.0; + if ((ewald_order&2) && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double x = g_ewald*r; register double s = force->qqrd2e*q[i]*q[j], t = 1.0/(1.0+EWALD_P*x); f = s*(1.0-factor_coul)/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-f; - if (eflag) one.eng_coul = t-f; + eng += t-f; } else { // table real space register float t = rsq; @@ -1141,12 +1141,10 @@ void PairBuckCoul::single(int i, int j, int itype, int jtype, register double f = (rsq-rtable[k])*drtable[k], qiqj = q[i]*q[j]; t = (1.0-factor_coul)*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t); - if (eflag) one.eng_coul = qiqj*(etable[k]+f*detable[k]-t); + eng += qiqj*(etable[k]+f*detable[k]-t); } - } - else force_coul = 0.0; + } else force_coul = 0.0; - one.eng_vdwl = 0.0; if (rsq < cut_bucksq[itype][jtype]) { // buckingham register double expr = factor_buck*exp(-sqrt(rsq)*rhoinv[itype][jtype]); r6inv = r2inv*r2inv*r2inv; @@ -1155,18 +1153,18 @@ void PairBuckCoul::single(int i, int j, int itype, int jtype, x2 = a2*exp(-x2)*buck_c[itype][jtype]; force_buck = buck1[itype][jtype]*r*expr- g8*(((6.0*a2+6.0)*a2+3.0)*a2+a2)*x2*rsq+t*buck2[itype][jtype]; - if (eflag) one.eng_vdwl = buck_a[itype][jtype]*expr- + eng += buck_a[itype][jtype]*expr- g6*((a2+1.0)*a2+0.5)*x2+t*buck_c[itype][jtype]; } else { // cut force_buck = buck1[itype][jtype]*r*expr-factor_buck*buck_c[itype][jtype]*r6inv; - if (eflag) one.eng_vdwl = buck_a[itype][jtype]*expr- - factor_buck*(buck_c[itype][jtype]*r6inv-offset[itype][jtype]); + eng += buck_a[itype][jtype]*expr- + factor_buck*(buck_c[itype][jtype]*r6inv-offset[itype][jtype]); } - } - else force_buck = 0.0; + } else force_buck = 0.0; - one.fforce = (force_coul+force_buck)*r2inv; + fforce = (force_coul+force_buck)*r2inv; + return eng; } diff --git a/src/USER-EWALDN/pair_buck_coul.h b/src/USER-EWALDN/pair_buck_coul.h index e0e584cfd2..0684dc9ce4 100644 --- a/src/USER-EWALDN/pair_buck_coul.h +++ b/src/USER-EWALDN/pair_buck_coul.h @@ -36,7 +36,7 @@ class PairBuckCoul : public Pair { void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void *extract(char *); void compute_inner(); diff --git a/src/USER-EWALDN/pair_lj_coul.cpp b/src/USER-EWALDN/pair_lj_coul.cpp index 531b538503..4f8b0ba235 100644 --- a/src/USER-EWALDN/pair_lj_coul.cpp +++ b/src/USER-EWALDN/pair_lj_coul.cpp @@ -1107,23 +1107,23 @@ void PairLJCoul::free_tables() /* ---------------------------------------------------------------------- */ -void PairLJCoul::single(int i, int j, int itype, int jtype, - double rsq, - double factor_coul, double factor_lj, - int eflag, One &one) +double PairLJCoul::single(int i, int j, int itype, int jtype, + double rsq, double factor_coul, double factor_lj, + double &fforce) { double r2inv, r6inv, force_coul, force_lj; double g2 = g_ewald*g_ewald, g6 = g2*g2*g2, g8 = g6*g2, *q = atom->q; + double eng = 0.0; + r2inv = 1.0/rsq; - one.eng_coul = 0.0; if ((ewald_order&2) && (rsq < cut_coulsq)) { // coulombic if (!ncoultablebits || rsq <= tabinnersq) { // series real space register double r = sqrt(rsq), x = g_ewald*r; register double s = force->qqrd2e*q[i]*q[j], t = 1.0/(1.0+EWALD_P*x); r = s*(1.0-factor_coul)/r; s *= g_ewald*exp(-x*x); force_coul = (t *= ((((t*A5+A4)*t+A3)*t+A2)*t+A1)*s/x)+EWALD_F*s-r; - if (eflag) one.eng_coul = t-r; + eng += t-r; } else { // table real space register float t = rsq; @@ -1131,12 +1131,10 @@ void PairLJCoul::single(int i, int j, int itype, int jtype, register double f = (rsq-rtable[k])*drtable[k], qiqj = q[i]*q[j]; t = (1.0-factor_coul)*(ctable[k]+f*dctable[k]); force_coul = qiqj*(ftable[k]+f*dftable[k]-t); - if (eflag) one.eng_coul = qiqj*(etable[k]+f*detable[k]-t); + eng += qiqj*(etable[k]+f*detable[k]-t); } - } - else force_coul = 0.0; + } else force_coul = 0.0; - one.eng_vdwl = 0.0; if (rsq < cut_ljsq[itype][jtype]) { // lennard-jones r6inv = r2inv*r2inv*r2inv; if (ewald_order&64) { // long-range @@ -1144,17 +1142,16 @@ void PairLJCoul::single(int i, int j, int itype, int jtype, x2 = a2*exp(-x2)*lj4[itype][jtype]; force_lj = factor_lj*(r6inv *= r6inv)*lj1[itype][jtype]- g8*(((6.0*a2+6.0)*a2+3.0)*a2+a2)*x2*rsq+t*lj2[itype][jtype]; - if (eflag) one.eng_vdwl = factor_lj*r6inv*lj3[itype][jtype]- + eng += factor_lj*r6inv*lj3[itype][jtype]- g6*((a2+1.0)*a2+0.5)*x2+t*lj4[itype][jtype]; } else { // cut force_lj = factor_lj*r6inv*(lj1[itype][jtype]*r6inv-lj2[itype][jtype]); - if (eflag) one.eng_vdwl = factor_lj*(r6inv*(r6inv*lj3[itype][jtype]- - lj4[itype][jtype])-offset[itype][jtype]); + eng += factor_lj*(r6inv*(r6inv*lj3[itype][jtype]- + lj4[itype][jtype])-offset[itype][jtype]); } - } - else force_lj = 0.0; + } else force_lj = 0.0; - one.fforce = (force_coul+force_lj)*r2inv; + fforce = (force_coul+force_lj)*r2inv; + return eng; } - diff --git a/src/USER-EWALDN/pair_lj_coul.h b/src/USER-EWALDN/pair_lj_coul.h index b2be4af355..d54c45c496 100644 --- a/src/USER-EWALDN/pair_lj_coul.h +++ b/src/USER-EWALDN/pair_lj_coul.h @@ -35,7 +35,7 @@ class PairLJCoul : public Pair { void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void *extract(char *); void compute_inner(); diff --git a/src/bond.h b/src/bond.h index 4ca8580626..e879c0e004 100644 --- a/src/bond.h +++ b/src/bond.h @@ -38,7 +38,7 @@ class Bond : protected Pointers { virtual double equilibrium_distance(int) = 0; virtual void write_restart(FILE *) = 0; virtual void read_restart(FILE *) = 0; - virtual void single(int, double, int, int, double &) = 0; + virtual double single(int, double, int, int) = 0; virtual double memory_usage(); protected: diff --git a/src/bond_hybrid.h b/src/bond_hybrid.h index 510fd0974f..bc10341335 100644 --- a/src/bond_hybrid.h +++ b/src/bond_hybrid.h @@ -32,7 +32,7 @@ class BondHybrid : public Bond { double equilibrium_distance(int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, double, int, int, double &); + double single(int, double, int, int); double memory_usage(); private: diff --git a/src/compute.cpp b/src/compute.cpp index 2ba76708fb..47e1bbb555 100644 --- a/src/compute.cpp +++ b/src/compute.cpp @@ -14,6 +14,7 @@ #include "mpi.h" #include "stdlib.h" #include "string.h" +#include "ctype.h" #include "compute.h" #include "group.h" #include "domain.h" @@ -32,12 +33,18 @@ Compute::Compute(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) if (narg < 3) error->all("Illegal compute command"); // compute ID, group, and style + // ID must be all alphanumeric chars or underscores int n = strlen(arg[0]) + 1; id = new char[n]; strcpy(id,arg[0]); + for (int i = 0; i < n-1; i++) + if (!isalnum(id[i]) && id[i] != '_') + error->all("Compute ID must be alphanumeric or underscore characters"); + igroup = group->find(arg[1]); + if (igroup == -1) error->all("Could not find compute group ID"); groupbit = group->bitmask[igroup]; n = strlen(arg[2]) + 1; @@ -53,10 +60,9 @@ Compute::Compute(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) scalar_flag = vector_flag = peratom_flag = 0; tempflag = pressflag = peflag = 0; pressatomflag = peatomflag = 0; + id_pre = NULL; timeflag = 0; invoked = 0; - npre = 0; - id_pre = NULL; comm_forward = comm_reverse = 0; // set modify defaults @@ -76,8 +82,6 @@ Compute::~Compute() { delete [] id; delete [] style; - - for (int i = 0; i < npre; i++) delete [] id_pre[i]; delete [] id_pre; memory->sfree(tlist); @@ -117,7 +121,7 @@ void Compute::modify_params(int narg, char **arg) search from top downward, since list of times is in decreasing order ------------------------------------------------------------------------- */ -void Compute::add_step(int ntimestep) +void Compute::addstep(int ntimestep) { // i = location in list to insert ntimestep @@ -149,7 +153,7 @@ void Compute::add_step(int ntimestep) search from top downward, since list of times is in decreasing order ------------------------------------------------------------------------- */ -int Compute::match_step(int ntimestep) +int Compute::matchstep(int ntimestep) { for (int i = ntime-1; i >= 0; i--) { if (ntimestep < tlist[i]) return 0; diff --git a/src/compute.h b/src/compute.h index bcffe1203e..efe24a4d1f 100644 --- a/src/compute.h +++ b/src/compute.h @@ -33,8 +33,10 @@ class Compute : protected Pointers { int size_vector; // N = size of global vector int peratom_flag; // 0/1 if compute_peratom() function exists int size_peratom; // 0 = scalar_atom, N = size of vector_atom + int extscalar; // 0/1 if scalar is intensive/extensive + int extvector; // 0/1/-1 if vector is all int/ext/extlist + int *extlist; // list of 0/1 int/ext for each vec component - int extensive; // 0/1 if scalar,vector are intensive/extensive values int tempflag; // 1 if Compute can be used as temperature // must have both compute_scalar, compute_vector int pressflag; // 1 if Compute can be used as pressure (uses virial) @@ -43,17 +45,17 @@ class Compute : protected Pointers { int peflag; // 1 if Compute calculates PE (uses Force energies) int peatomflag; // 1 if Compute calculates per-atom PE + char *id_pre; // ID of pre-compute the Compute may store + int timeflag; // 1 if Compute stores list of timesteps it's called on int ntime; // # of entries in time list int maxtime; // max # of entries time list can hold int *tlist; // time list of steps the Compute is called on - int invoked; // 1 if Compute was invoked (e.g. by a variable) + + int invoked; // set when Compute is invoked, to avoid re-invoking double dof; // degrees-of-freedom for temperature - int npre; // # of computes to compute before this one - char **id_pre; // IDs of Computes to compute before this one - int comm_forward; // size of forward communication (0 if none) int comm_reverse; // size of reverse communication (0 if none) @@ -71,8 +73,8 @@ class Compute : protected Pointers { virtual int pack_reverse_comm(int, int, double *) {return 0;} virtual void unpack_reverse_comm(int, int *, double *) {} - void add_step(int); - int match_step(int); + void addstep(int); + int matchstep(int); virtual double memory_usage() {return 0.0;} diff --git a/src/compute_attribute_atom.cpp b/src/compute_attribute_atom.cpp deleted file mode 100644 index c702933260..0000000000 --- a/src/compute_attribute_atom.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#include "string.h" -#include "compute_attribute_atom.h" -#include "atom.h" -#include "domain.h" -#include "memory.h" -#include "error.h" - -using namespace LAMMPS_NS; - -enum{X,Y,Z,XU,YU,ZU,VX,VY,VZ,FX,FY,FZ,XYZ,V,F}; - -/* --------------------------------------------------------------------- */ - -ComputeAttributeAtom::ComputeAttributeAtom(LAMMPS *lmp, int narg, char **arg) : - Compute(lmp, narg, arg) -{ - if (narg != 4) error->all("Illegal compute ke/atom command"); - - peratom_flag = 1; - size_peratom = 0; - - if (strcmp(arg[3],"x") == 0) which = X; - else if (strcmp(arg[3],"y") == 0) which = Y; - else if (strcmp(arg[3],"z") == 0) which = Z; - else if (strcmp(arg[3],"xu") == 0) which = XU; - else if (strcmp(arg[3],"yu") == 0) which = YU; - else if (strcmp(arg[3],"zu") == 0) which = ZU; - else if (strcmp(arg[3],"vx") == 0) which = VX; - else if (strcmp(arg[3],"vy") == 0) which = VY; - else if (strcmp(arg[3],"vz") == 0) which = VZ; - else if (strcmp(arg[3],"fx") == 0) which = FX; - else if (strcmp(arg[3],"fy") == 0) which = FY; - else if (strcmp(arg[3],"fz") == 0) which = FZ; - - else if (strcmp(arg[3],"xyz") == 0) { - which = XYZ; - size_peratom = 3; - } else if (strcmp(arg[3],"v") == 0) { - which = V; - size_peratom = 3; - } else if (strcmp(arg[3],"f") == 0) { - which = F; - size_peratom = 3; - } else error->all("Illegal compute attribute/atom command"); - - nmax = 0; - s_attribute = NULL; - v_attribute = NULL; -} - -/* ---------------------------------------------------------------------- */ - -ComputeAttributeAtom::~ComputeAttributeAtom() -{ - memory->sfree(s_attribute); - memory->destroy_2d_double_array(v_attribute); -} - -/* ---------------------------------------------------------------------- */ - -void ComputeAttributeAtom::compute_peratom() -{ - // grow attribute array if necessary - - if (atom->nlocal > nmax) { - if (size_peratom == 0) { - memory->sfree(s_attribute); - nmax = atom->nmax; - s_attribute = (double *) - memory->smalloc(nmax*sizeof(double), - "compute/attribute/atom:s_attribute"); - scalar_atom = s_attribute; - } else { - memory->destroy_2d_double_array(v_attribute); - nmax = atom->nmax; - v_attribute = - memory->create_2d_double_array(nmax,size_peratom, - "compute/attribute/atom:v_attribute"); - vector_atom = v_attribute; - } - } - - // fill attribute vector with appropriate atom value - // or simply set pointer to exisitng atom vector - - double xprd = domain->xprd; - double yprd = domain->yprd; - double zprd = domain->zprd; - - double **x = atom->x; - double **v = atom->v; - double **f = atom->f; - int *mask = atom->mask; - int *image = atom->image; - int nlocal = atom->nlocal; - - if (which == X) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = x[i][0]; - else s_attribute[i] = 0.0; - } else if (which == Y) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = x[i][1]; - else s_attribute[i] = 0.0; - } else if (which == Z) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = x[i][2]; - else s_attribute[i] = 0.0; - - } else if (which == XU) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - s_attribute[i] = x[i][0] + ((image[i] & 1023) - 512) * xprd; - else s_attribute[i] = 0.0; - } else if (which == YU) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - s_attribute[i] = x[i][1] + ((image[i] >> 10 & 1023) - 512) * yprd; - else s_attribute[i] = 0.0; - } else if (which == ZU) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - s_attribute[i] = x[i][2] + ((image[i] >> 20) - 512) * zprd; - else s_attribute[i] = 0.0; - - } else if (which == VX) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = v[i][0]; - else s_attribute[i] = 0.0; - } else if (which == VY) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = v[i][1]; - else s_attribute[i] = 0.0; - } else if (which == VZ) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = v[i][2]; - else s_attribute[i] = 0.0; - - } else if (which == FX) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = f[i][0]; - else s_attribute[i] = 0.0; - } else if (which == FY) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = f[i][1]; - else s_attribute[i] = 0.0; - } else if (which == FZ) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_attribute[i] = f[i][2]; - else s_attribute[i] = 0.0; - - } else if (which == XYZ) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - v_attribute[i][0] = x[i][0]; - v_attribute[i][1] = x[i][1]; - v_attribute[i][2] = x[i][2]; - } else { - v_attribute[i][0] = 0.0; - v_attribute[i][1] = 0.0; - v_attribute[i][2] = 0.0; - } - } else if (which == V) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - v_attribute[i][0] = v[i][0]; - v_attribute[i][1] = v[i][1]; - v_attribute[i][2] = v[i][2]; - } else { - v_attribute[i][0] = 0.0; - v_attribute[i][1] = 0.0; - v_attribute[i][2] = 0.0; - } - } else if (which == F) { - for (int i = 0; i < nlocal; i++) - if (mask[i] & groupbit) { - v_attribute[i][0] = f[i][0]; - v_attribute[i][1] = f[i][1]; - v_attribute[i][2] = f[i][2]; - } else { - v_attribute[i][0] = 0.0; - v_attribute[i][1] = 0.0; - v_attribute[i][2] = 0.0; - } - } -} - -/* ---------------------------------------------------------------------- - memory usage of local atom-based array -------------------------------------------------------------------------- */ - -double ComputeAttributeAtom::memory_usage() -{ - double bytes = 0.0; - if (size_peratom == 0) bytes = nmax * sizeof(double); - else bytes = size_peratom * nmax * sizeof(double); - return bytes; -} diff --git a/src/compute_attribute_atom.h b/src/compute_attribute_atom.h deleted file mode 100644 index 06f5b3362b..0000000000 --- a/src/compute_attribute_atom.h +++ /dev/null @@ -1,36 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifndef COMPUTE_ATTRIBUTE_ATOM_H -#define COMPUTE_ATTRIBUTE_ATOM_H - -#include "compute.h" - -namespace LAMMPS_NS { - -class ComputeAttributeAtom : public Compute { - public: - ComputeAttributeAtom(class LAMMPS *, int, char **); - ~ComputeAttributeAtom(); - void init() {} - void compute_peratom(); - double memory_usage(); - - private: - int which,allocate,nmax; - double *s_attribute,**v_attribute; -}; - -} - -#endif diff --git a/src/compute_centro_atom.cpp b/src/compute_centro_atom.cpp index 1d5e605057..cf4b2d63be 100644 --- a/src/compute_centro_atom.cpp +++ b/src/compute_centro_atom.cpp @@ -27,6 +27,8 @@ using namespace LAMMPS_NS; +#define INVOKED_PERATOM 4 + /* ---------------------------------------------------------------------- */ ComputeCentroAtom::ComputeCentroAtom(LAMMPS *lmp, int narg, char **arg) : @@ -89,6 +91,8 @@ void ComputeCentroAtom::compute_peratom() int *ilist,*jlist,*numneigh,**firstneigh; double pairs[66]; + invoked |= INVOKED_PERATOM; + // grow centro array if necessary if (atom->nlocal > nmax) { diff --git a/src/compute_coord_atom.cpp b/src/compute_coord_atom.cpp index 025703471b..f9e398f453 100644 --- a/src/compute_coord_atom.cpp +++ b/src/compute_coord_atom.cpp @@ -27,6 +27,8 @@ using namespace LAMMPS_NS; +#define INVOKED_PERATOM 4 + /* ---------------------------------------------------------------------- */ ComputeCoordAtom::ComputeCoordAtom(LAMMPS *lmp, int narg, char **arg) : @@ -88,6 +90,8 @@ void ComputeCoordAtom::compute_peratom() double xtmp,ytmp,ztmp,delx,dely,delz,rsq; int *ilist,*jlist,*numneigh,**firstneigh; + invoked |= INVOKED_PERATOM; + // grow coordination array if necessary if (atom->nlocal > nmax) { diff --git a/src/compute_ke_atom.cpp b/src/compute_ke_atom.cpp index fbbccec9b4..e2417a4e6d 100644 --- a/src/compute_ke_atom.cpp +++ b/src/compute_ke_atom.cpp @@ -22,6 +22,8 @@ using namespace LAMMPS_NS; +#define INVOKED_PERATOM 4 + /* ---------------------------------------------------------------------- */ ComputeKEAtom::ComputeKEAtom(LAMMPS *lmp, int narg, char **arg) : @@ -58,6 +60,8 @@ void ComputeKEAtom::init() void ComputeKEAtom::compute_peratom() { + invoked |= INVOKED_PERATOM; + // grow ke array if necessary if (atom->nlocal > nmax) { diff --git a/src/compute_pe.cpp b/src/compute_pe.cpp index e3f5bbba38..4788785dc5 100644 --- a/src/compute_pe.cpp +++ b/src/compute_pe.cpp @@ -28,6 +28,8 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 + /* ---------------------------------------------------------------------- */ ComputePE::ComputePE(LAMMPS *lmp, int narg, char **arg) : @@ -62,7 +64,7 @@ ComputePE::ComputePE(LAMMPS *lmp, int narg, char **arg) : // settings scalar_flag = 1; - extensive = 1; + extscalar = 1; peflag = 1; timeflag = 1; } @@ -71,9 +73,9 @@ ComputePE::ComputePE(LAMMPS *lmp, int narg, char **arg) : double ComputePE::compute_scalar() { - invoked = 1; - double one = 0.0; + invoked |= INVOKED_SCALAR; + double one = 0.0; if (pairflag && force->pair) one += force->pair->eng_vdwl + force->pair->eng_coul; diff --git a/src/compute_pe_atom.cpp b/src/compute_pe_atom.cpp index dcea56ddb0..20fd75318c 100755 --- a/src/compute_pe_atom.cpp +++ b/src/compute_pe_atom.cpp @@ -26,6 +26,8 @@ using namespace LAMMPS_NS; +#define INVOKED_PERATOM 4 + /* ---------------------------------------------------------------------- */ ComputePEAtom::ComputePEAtom(LAMMPS *lmp, int narg, char **arg) : @@ -74,7 +76,7 @@ void ComputePEAtom::compute_peratom() { int i; - invoked = 1; + invoked |= INVOKED_PERATOM; // grow local energy array if necessary diff --git a/src/compute_pressure.cpp b/src/compute_pressure.cpp index a81cafc3a5..537dc93525 100644 --- a/src/compute_pressure.cpp +++ b/src/compute_pressure.cpp @@ -30,6 +30,9 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 + /* ---------------------------------------------------------------------- */ ComputePressure::ComputePressure(LAMMPS *lmp, int narg, char **arg) : @@ -40,21 +43,19 @@ ComputePressure::ComputePressure(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; pressflag = 1; timeflag = 1; // store temperature ID used by pressure computation // insure it is valid for temperature computation - npre = 1; - id_pre = new char*[1]; int n = strlen(arg[3]) + 1; - id_pre[0] = new char[n]; - strcpy(id_pre[0],arg[3]); - - int icompute = modify->find_compute(id_pre[0]); + id_pre = new char[n]; + strcpy(id_pre,arg[3]); + int icompute = modify->find_compute(id_pre); if (icompute < 0) error->all("Could not find compute pressure temp ID"); if (modify->compute[icompute]->tempflag == 0) error->all("Compute pressure temp ID does not compute temperature"); @@ -109,7 +110,7 @@ void ComputePressure::init() // set temperature used by pressure - int icompute = modify->find_compute(id_pre[0]); + int icompute = modify->find_compute(id_pre); if (icompute < 0) error->all("Could not find compute pressure temp ID"); temperature = modify->compute[icompute]; @@ -153,16 +154,25 @@ void ComputePressure::init() /* ---------------------------------------------------------------------- compute total pressure, averaged over Pxx, Pyy, Pzz - assume temperature has already been computed ------------------------------------------------------------------------- */ double ComputePressure::compute_scalar() { + invoked |= INVOKED_SCALAR; + + // invoke temperature it it hasn't been already + + double t; + if (keflag) { + if (temperature->invoked & INVOKED_SCALAR) t = temperature->scalar; + else t = temperature->compute_scalar(); + } + if (dimension == 3) { inv_volume = 1.0 / (domain->xprd * domain->yprd * domain->zprd); virial_compute(3,3); if (keflag) - scalar = (temperature->dof * boltz * temperature->scalar + + scalar = (temperature->dof * boltz * t + virial[0] + virial[1] + virial[2]) / 3.0 * inv_volume * nktv2p; else scalar = (virial[0] + virial[1] + virial[2]) / 3.0 * inv_volume * nktv2p; @@ -170,7 +180,7 @@ double ComputePressure::compute_scalar() inv_volume = 1.0 / (domain->xprd * domain->yprd); virial_compute(2,2); if (keflag) - scalar = (temperature->dof * boltz * temperature->scalar + + scalar = (temperature->dof * boltz * t + virial[0] + virial[1]) / 2.0 * inv_volume * nktv2p; else scalar = (virial[0] + virial[1]) / 2.0 * inv_volume * nktv2p; @@ -186,11 +196,21 @@ double ComputePressure::compute_scalar() void ComputePressure::compute_vector() { + invoked |= INVOKED_VECTOR; + + // invoke temperature it it hasn't been already + + double *ke_tensor; + if (keflag) { + if (!(temperature->invoked & INVOKED_VECTOR)) + temperature->compute_vector(); + ke_tensor = temperature->vector; + } + if (dimension == 3) { inv_volume = 1.0 / (domain->xprd * domain->yprd * domain->zprd); virial_compute(6,3); if (keflag) { - double *ke_tensor = temperature->vector; for (int i = 0; i < 6; i++) vector[i] = (ke_tensor[i] + virial[i]) * inv_volume * nktv2p; } else @@ -200,7 +220,6 @@ void ComputePressure::compute_vector() inv_volume = 1.0 / (domain->xprd * domain->yprd); virial_compute(4,2); if (keflag) { - double *ke_tensor = temperature->vector; vector[0] = (ke_tensor[0] + virial[0]) * inv_volume * nktv2p; vector[1] = (ke_tensor[1] + virial[1]) * inv_volume * nktv2p; vector[3] = (ke_tensor[3] + virial[3]) * inv_volume * nktv2p; @@ -219,7 +238,6 @@ void ComputePressure::virial_compute(int n, int ndiag) int i,j; double v[6],*vcomponent; - invoked = 1; for (i = 0; i < n; i++) v[i] = 0.0; // sum contributions to virial from forces and fixes diff --git a/src/compute_rotate_dipole.cpp b/src/compute_rotate_dipole.cpp index 2830291aac..09b264c53a 100644 --- a/src/compute_rotate_dipole.cpp +++ b/src/compute_rotate_dipole.cpp @@ -20,6 +20,7 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 #define INERTIA3D 0.4 // moments of inertia for sphere and disk #define INERTIA2D 0.5 @@ -34,7 +35,7 @@ ComputeRotateDipole::ComputeRotateDipole(LAMMPS *lmp, int narg, char **arg) : error->all("Compute rotate/dipole requires atom attributes dipole, omega"); scalar_flag = 1; - extensive = 1; + extscalar = 1; inertia = NULL; } @@ -68,6 +69,8 @@ void ComputeRotateDipole::init() double ComputeRotateDipole::compute_scalar() { + invoked |= INVOKED_SCALAR; + double *dipole = atom->dipole; double **omega = atom->omega; int *type = atom->type; diff --git a/src/compute_rotate_gran.cpp b/src/compute_rotate_gran.cpp index a1cd49ef6f..32e21525c2 100644 --- a/src/compute_rotate_gran.cpp +++ b/src/compute_rotate_gran.cpp @@ -21,6 +21,7 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 #define INERTIA3D 0.4 // moments of inertia for sphere and disk #define INERTIA2D 0.5 @@ -36,7 +37,7 @@ ComputeRotateGran::ComputeRotateGran(LAMMPS *lmp, int narg, char **arg) : "radius, rmass, omega"); scalar_flag = 1; - extensive = 1; + extscalar = 1; } /* ---------------------------------------------------------------------- */ @@ -51,6 +52,8 @@ void ComputeRotateGran::init() double ComputeRotateGran::compute_scalar() { + invoked |= INVOKED_SCALAR; + double **omega = atom->omega; double *radius = atom->radius; double *rmass = atom->rmass; diff --git a/src/compute_stress_atom.cpp b/src/compute_stress_atom.cpp index b737607c55..86d89897f9 100644 --- a/src/compute_stress_atom.cpp +++ b/src/compute_stress_atom.cpp @@ -27,6 +27,8 @@ using namespace LAMMPS_NS; +#define INVOKED_PERATOM 4 + /* ---------------------------------------------------------------------- */ ComputeStressAtom::ComputeStressAtom(LAMMPS *lmp, int narg, char **arg) : @@ -78,7 +80,7 @@ void ComputeStressAtom::compute_peratom() { int i,j; - invoked = 1; + invoked |= INVOKED_PERATOM; // grow local stress array if necessary diff --git a/src/compute_sum.cpp b/src/compute_sum.cpp index bc86c70c7b..c2f73effba 100644 --- a/src/compute_sum.cpp +++ b/src/compute_sum.cpp @@ -12,16 +12,27 @@ ------------------------------------------------------------------------- */ #include "string.h" +#include "stdlib.h" #include "compute_sum.h" #include "atom.h" +#include "update.h" #include "modify.h" +#include "fix.h" #include "force.h" #include "comm.h" +#include "input.h" +#include "variable.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 +#define INVOKED_PERATOM 4 + +enum{X,V,F,COMPUTE,FIX,VARIABLE}; + /* ---------------------------------------------------------------------- */ ComputeSum::ComputeSum(LAMMPS *lmp, int narg, char **arg) : @@ -29,74 +40,171 @@ ComputeSum::ComputeSum(LAMMPS *lmp, int narg, char **arg) : { if (narg < 4) error->all("Illegal compute sum command"); - // store pre-compute IDs + // parse remaining values - npre = narg - 3; - id_pre = new char*[npre]; - for (int i = 0; i < npre; i++) { - int iarg = i + 3; - int n = strlen(arg[iarg]) + 1; - id_pre[i] = new char[n]; - strcpy(id_pre[i],arg[iarg]); + which = new int[narg-3]; + argindex = new int[narg-3]; + ids = new char*[narg-3]; + value2index = new int[narg-3]; + nvalues = 0; + + int iarg = 3; + while (iarg < narg) { + ids[nvalues] = NULL; + + if (strcmp(arg[iarg],"x") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"y") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"z") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 2; + + } else if (strcmp(arg[iarg],"vx") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"vy") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"vz") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 2; + + } else if (strcmp(arg[iarg],"fx") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"fy") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"fz") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 2; + + } else if ((strncmp(arg[iarg],"c_",2) == 0) || + (strncmp(arg[iarg],"f_",2) == 0) || + (strncmp(arg[iarg],"v_",2) == 0)) { + if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE; + else if (arg[iarg][0] == 'f') which[nvalues] = FIX; + else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE; + + int n = strlen(arg[iarg]); + char *suffix = new char[n]; + strcpy(suffix,&arg[iarg][2]); + + char *ptr = strchr(suffix,'['); + if (ptr) { + if (suffix[strlen(suffix)-1] != ']') + error->all("Illegal compute sum command"); + argindex[nvalues] = atoi(ptr+1); + *ptr = '\0'; + } else argindex[nvalues] = 0; + + n = strlen(suffix) + 1; + ids[nvalues] = new char[n]; + strcpy(ids[nvalues],suffix); + nvalues++; + delete [] suffix; + + } else error->all("Illegal compute sum command"); + + iarg++; } - compute = new Compute*[npre]; + // setup and error check - // all sub-computes must be peratom - // check consistency of sub-computes for scalar & vector output - - int icompute; - for (int i = 0; i < npre; i++) { - icompute = modify->find_compute(id_pre[i]); - if (icompute < 0) - error->all("Could not find compute sum/atom pre-compute ID"); - if (modify->compute[icompute]->peratom_flag == 0) - error->all("Compute sum compute is not a per-atom compute"); + for (int i = 0; i < nvalues; i++) { + if (which[i] == COMPUTE) { + int icompute = modify->find_compute(ids[i]); + if (icompute < 0) + error->all("Compute ID for compute sum does not exist"); + if (modify->compute[icompute]->peratom_flag == 0) + error->all("Compute sum compute does not calculate per-atom values"); + if (argindex[i] == 0 && modify->compute[icompute]->size_peratom != 0) + error->all("Compute sum compute does not calculate a per-atom scalar"); + if (argindex[i] && modify->compute[icompute]->size_peratom == 0) + error->all("Compute sum compute does not calculate a per-atom vector"); + } else if (which[i] == FIX) { + int ifix = modify->find_fix(ids[i]); + if (ifix < 0) + error->all("Fix ID for compute sum does not exist"); + if (modify->fix[ifix]->peratom_flag == 0) + error->all("Compute sum fix does not calculate per-atom values"); + if (argindex[i] == 0 && modify->fix[ifix]->size_peratom != 0) + error->all("Compute sum fix does not calculate a per-atom scalar"); + if (argindex[i] && modify->fix[ifix]->size_peratom == 0) + error->all("Compute sum fix does not calculate a per-atom vector"); + } else if (which[i] == VARIABLE) { + int ivariable = input->variable->find(ids[i]); + if (ivariable < 0) + error->all("Variable name for compute sum does not exist"); + if (input->variable->atomstyle(ivariable) == 0) + error->all("Compute sum variable is not atom-style variable"); + } } - peratom_flag = 0; - extensive = 0; + // this compute produces either a scalar or vector - icompute = modify->find_compute(id_pre[0]); - int size = modify->compute[icompute]->size_peratom; - if (size == 0) { + if (nvalues == 1) { scalar_flag = 1; + extscalar = 1; vector = NULL; onevec = NULL; } else { vector_flag = 1; - size_vector = size; + size_vector = nvalues; + extvector = 1; vector = new double[size_vector]; onevec = new double[size_vector]; } - for (int i = 1; i < npre; i++) { - icompute = modify->find_compute(id_pre[i]); - if (modify->compute[icompute]->size_peratom != size) - error->all("Inconsistent sizes of compute sum compute quantities"); - } + maxatom = 0; + varatom = NULL; } /* ---------------------------------------------------------------------- */ ComputeSum::~ComputeSum() { - delete [] compute; + delete [] which; + delete [] argindex; + for (int m = 0; m < nvalues; m++) delete [] ids[m]; + delete [] ids; + delete [] value2index; + delete [] vector; delete [] onevec; + + memory->sfree(varatom); } /* ---------------------------------------------------------------------- */ void ComputeSum::init() { - // set ptrs to Computes used as pre-computes by this compute + // set indices and check validity of all computes,fixes,variables - for (int i = 0; i < npre; i++) { - int icompute = modify->find_compute(id_pre[i]); - if (icompute < 0) - error->all("Could not find compute sum/atom pre-compute ID"); - compute[i] = modify->compute[icompute]; + for (int m = 0; m < nvalues; m++) { + if (which[m] == COMPUTE) { + int icompute = modify->find_compute(ids[m]); + if (icompute < 0) + error->all("Compute ID for compute sum does not exist"); + value2index[m] = icompute; + + } else if (which[m] == FIX) { + int ifix = modify->find_fix(ids[m]); + if (ifix < 0) + error->all("Fix ID for compute sum does not exist"); + value2index[m] = ifix; + + } else if (which[m] == VARIABLE) { + int ivariable = input->variable->find(ids[m]); + if (ivariable < 0) + error->all("Variable name for compute sum does not exist"); + value2index[m] = ivariable; + + } else value2index[m] = -1; } } @@ -104,31 +212,10 @@ void ComputeSum::init() double ComputeSum::compute_scalar() { - int i; - - // invoke all the pre-computes - // this is the only compute that does this - // done b/c pre-computes are per-atom and this compute is not - - for (int icompute = 0; icompute < npre; icompute++) - compute[icompute]->compute_peratom(); - - // compute scalar quantity by summing over atom scalars - // only include atoms in group - - int *mask = atom->mask; - int nlocal = atom->nlocal; - - double one = 0.0; - - for (int icompute = 0; icompute < npre; icompute++) { - double *scalar_atom = compute[icompute]->scalar_atom; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) one += scalar_atom[i]; - } + invoked |= INVOKED_SCALAR; + double one = compute_one(0); MPI_Allreduce(&one,&scalar,1,MPI_DOUBLE,MPI_SUM,world); - return scalar; } @@ -136,30 +223,100 @@ double ComputeSum::compute_scalar() void ComputeSum::compute_vector() { - int i,j; + invoked |= INVOKED_VECTOR; - // invoke all the pre-computes - // this is the only compute that does this - // done b/c pre-computes are per-atom and this compute is not + for (int m = 0; m < nvalues; m++) onevec[m] = compute_one(m); + MPI_Allreduce(onevec,vector,size_vector,MPI_DOUBLE,MPI_SUM,world); +} - for (int icompute = 0; icompute < npre; icompute++) - compute[icompute]->compute_peratom(); +/* ---------------------------------------------------------------------- */ - // compute vector quantity by summing over atom vectors +double ComputeSum::compute_one(int m) +{ + int i; + + // invoke the appropriate attribute,compute,fix,variable + // compute scalar quantity by summing over atom scalars // only include atoms in group int *mask = atom->mask; int nlocal = atom->nlocal; - for (j = 0; j < size_vector; j++) onevec[j] = 0.0; + int n = value2index[m]; + int j = argindex[m]; + double one = 0.0; - for (int icompute = 0; icompute < npre; icompute++) { - double **vector_atom = compute[icompute]->vector_atom; + if (which[m] == X) { + double **x = atom->x; for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - for (j = 0; j < size_vector; j++) - onevec[j] += vector_atom[i][j]; + if (mask[i] & groupbit) one += x[i][j]; + } else if (which[m] == V) { + double **v = atom->v; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) one += v[i][j]; + } else if (which[m] == F) { + double **f = atom->f; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) one += f[i][j]; + + // invoke compute if not previously invoked + + } else if (which[m] == COMPUTE) { + if (!(modify->compute[n]->invoked & INVOKED_PERATOM)) + modify->compute[n]->compute_peratom(); + + if (j == 0) { + double *compute_scalar = modify->compute[n]->scalar_atom; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) one += compute_scalar[i]; + } else { + double **compute_vector = modify->compute[n]->vector_atom; + int jm1 = j - 1; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) one += compute_vector[i][jm1]; + } + + // access fix fields, check if frequency is a match + + } else if (which[m] == FIX) { + if (update->ntimestep % modify->fix[n]->peratom_freq) + error->all("Fix used in compute sum not computed at compatible time"); + + if (j == 0) { + double *fix_scalar = modify->fix[n]->scalar_atom; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) one += fix_scalar[i]; + } else { + double **fix_vector = modify->fix[n]->vector_atom; + int jm1 = j - 1; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) one += fix_vector[i][jm1]; + } + + // evaluate atom-style variable + + } else if (which[m] == VARIABLE) { + if (nlocal > maxatom) { + maxatom = atom->nmax; + memory->sfree(varatom); + varatom = (double *) + memory->smalloc(maxatom*sizeof(double),"compute/sum:varatom"); + } + + input->variable->compute_atom(n,igroup,varatom,1,0); + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) one += varatom[i]; } - MPI_Allreduce(onevec,vector,size_vector,MPI_DOUBLE,MPI_SUM,world); + return one; +} + +/* ---------------------------------------------------------------------- + memory usage of varatom +------------------------------------------------------------------------- */ + +double ComputeSum::memory_usage() +{ + double bytes = maxatom * sizeof(double); + return bytes; } diff --git a/src/compute_sum.h b/src/compute_sum.h index d38e35017f..100ed43920 100644 --- a/src/compute_sum.h +++ b/src/compute_sum.h @@ -25,10 +25,18 @@ class ComputeSum : public Compute { void init(); double compute_scalar(); void compute_vector(); + double memory_usage(); private: + int nvalues; + int *which,*argindex,*value2index; + char **ids; double *onevec; - class Compute **compute; + + int maxatom; + double *varatom; + + double compute_one(int); }; } diff --git a/src/compute_sum_atom.cpp b/src/compute_sum_atom.cpp deleted file mode 100644 index 9d20496958..0000000000 --- a/src/compute_sum_atom.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#include "string.h" -#include "compute_sum_atom.h" -#include "atom.h" -#include "modify.h" -#include "force.h" -#include "comm.h" -#include "memory.h" -#include "error.h" - -using namespace LAMMPS_NS; - -/* ---------------------------------------------------------------------- */ - -ComputeSumAtom::ComputeSumAtom(LAMMPS *lmp, int narg, char **arg) : - Compute(lmp, narg, arg) -{ - if (narg < 5) error->all("Illegal compute sum/atom command"); - - // store pre-compute IDs - - npre = narg - 3; - id_pre = new char*[npre]; - for (int i = 0; i < npre; i++) { - int iarg = i + 3; - int n = strlen(arg[iarg]) + 1; - id_pre[i] = new char[n]; - strcpy(id_pre[i],arg[iarg]); - } - - compute = new Compute*[npre]; - - // all sub-computes must be peratom - // check consistency of sub-computes for scalar & vector output - - int icompute; - for (int i = 0; i < npre; i++) { - icompute = modify->find_compute(id_pre[i]); - if (icompute < 0) - error->all("Could not find compute sum/atom pre-compute ID"); - if (modify->compute[icompute]->peratom_flag == 0) - error->all("Compute sum/atom compute is not a per-atom compute"); - } - - peratom_flag = 1; - icompute = modify->find_compute(id_pre[0]); - size_peratom = modify->compute[icompute]->size_peratom; - - for (int i = 1; i < npre; i++) { - icompute = modify->find_compute(id_pre[i]); - if (modify->compute[icompute]->size_peratom != size_peratom) - error->all("Inconsistent sizes of compute sum/atom compute quantities"); - } - - // values generated by this compute - - nmax = 0; - s_value = NULL; - v_value = NULL; -} - -/* ---------------------------------------------------------------------- */ - -ComputeSumAtom::~ComputeSumAtom() -{ - delete [] compute; - memory->sfree(s_value); - memory->destroy_2d_double_array(v_value); -} - -/* ---------------------------------------------------------------------- */ - -void ComputeSumAtom::init() -{ - // set ptrs to Computes used as pre-computes by this compute - - for (int i = 0; i < npre; i++) { - int icompute = modify->find_compute(id_pre[i]); - if (icompute < 0) - error->all("Could not find compute sum/atom pre-compute ID"); - compute[i] = modify->compute[icompute]; - } -} - -/* ---------------------------------------------------------------------- */ - -void ComputeSumAtom::compute_peratom() -{ - int i,j,m; - - // grow sum array if necessary - - if (atom->nlocal > nmax) { - nmax = atom->nmax; - if (size_peratom == 0) { - memory->sfree(s_value); - s_value = (double *) - memory->smalloc(nmax*sizeof(double),"compute/sum/atom:s_value"); - scalar_atom = s_value; - } else { - memory->destroy_2d_double_array(v_value); - v_value = memory->create_2d_double_array(nmax,size_peratom, - "compute/sum/atom:v_value"); - vector_atom = v_value; - } - } - - // sum over pre-computes - // pre-computes of the pre-computes are not invoked - - int *mask = atom->mask; - int nlocal = atom->nlocal; - - if (size_peratom == 0) { - double *scalar = compute[0]->scalar_atom; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_value[i] = scalar[i]; - else s_value[i] = 0.0; - - for (m = 1; m < npre; m++) { - scalar = compute[m]->scalar_atom; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) s_value[i] += scalar[i]; - } - - } else { - double **vector = compute[0]->vector_atom; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - for (j = 0; j < size_peratom; j++) - v_value[i][j] = vector[i][j]; - else - for (j = 0; j < size_peratom; j++) - v_value[i][j] = 0.0; - - for (m = 1; m < npre; m++) { - vector = compute[m]->vector_atom; - for (j = 0; j < size_peratom; j++) - if (mask[i] & groupbit) v_value[i][j] += vector[i][j]; - } - } -} - -/* ---------------------------------------------------------------------- - memory usage of local atom-based array -------------------------------------------------------------------------- */ - -double ComputeSumAtom::memory_usage() -{ - double bytes = 0.0; - if (size_peratom == 0) bytes = nmax * sizeof(double); - else bytes = nmax*size_peratom * sizeof(double); - return bytes; -} diff --git a/src/compute_sum_atom.h b/src/compute_sum_atom.h deleted file mode 100644 index b2b67b5aae..0000000000 --- a/src/compute_sum_atom.h +++ /dev/null @@ -1,37 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifndef COMPUTE_SUM_ATOM_H -#define COMPUTE_SUM_ATOM_H - -#include "compute.h" - -namespace LAMMPS_NS { - -class ComputeSumAtom : public Compute { - public: - ComputeSumAtom(class LAMMPS *, int, char **); - ~ComputeSumAtom(); - void init(); - void compute_peratom(); - double memory_usage(); - - private: - int nmax; - class Compute **compute; - double *s_value,**v_value; -}; - -} - -#endif diff --git a/src/compute_temp.cpp b/src/compute_temp.cpp index 0806761bc2..7fecab3a4a 100644 --- a/src/compute_temp.cpp +++ b/src/compute_temp.cpp @@ -23,6 +23,9 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 + /* ---------------------------------------------------------------------- */ ComputeTemp::ComputeTemp(LAMMPS *lmp, int narg, char **arg) : @@ -32,7 +35,8 @@ ComputeTemp::ComputeTemp(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; tempflag = 1; vector = new double[6]; @@ -70,6 +74,8 @@ void ComputeTemp::recount() double ComputeTemp::compute_scalar() { + invoked |= INVOKED_SCALAR; + double **v = atom->v; double *mass = atom->mass; double *rmass = atom->rmass; @@ -102,6 +108,8 @@ void ComputeTemp::compute_vector() { int i; + invoked |= INVOKED_VECTOR; + double **v = atom->v; double *mass = atom->mass; double *rmass = atom->rmass; diff --git a/src/compute_temp_deform.cpp b/src/compute_temp_deform.cpp index bc48451155..2544ac7c56 100644 --- a/src/compute_temp_deform.cpp +++ b/src/compute_temp_deform.cpp @@ -30,6 +30,8 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 enum{NO_REMAP,X_REMAP,V_REMAP}; // same as fix_deform.cpp /* ---------------------------------------------------------------------- */ @@ -41,7 +43,8 @@ ComputeTempDeform::ComputeTempDeform(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; tempflag = 1; vector = new double[6]; @@ -95,6 +98,8 @@ double ComputeTempDeform::compute_scalar() { double lamda[3],vstream[3],vthermal[3]; + invoked |= INVOKED_SCALAR; + double **x = atom->x; double **v = atom->v; double *mass = atom->mass; @@ -153,6 +158,8 @@ void ComputeTempDeform::compute_vector() { double lamda[3],vstream[3],vthermal[3]; + invoked |= INVOKED_VECTOR; + double **x = atom->x; double **v = atom->v; double *mass = atom->mass; diff --git a/src/compute_temp_partial.cpp b/src/compute_temp_partial.cpp index d47382e2ab..df738e7360 100644 --- a/src/compute_temp_partial.cpp +++ b/src/compute_temp_partial.cpp @@ -23,6 +23,9 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 + /* ---------------------------------------------------------------------- */ ComputeTempPartial::ComputeTempPartial(LAMMPS *lmp, int narg, char **arg) : @@ -36,7 +39,8 @@ ComputeTempPartial::ComputeTempPartial(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; tempflag = 1; vector = new double[6]; @@ -74,6 +78,8 @@ void ComputeTempPartial::recount() double ComputeTempPartial::compute_scalar() { + invoked |= INVOKED_SCALAR; + double **v = atom->v; double *mass = atom->mass; double *rmass = atom->rmass; @@ -107,6 +113,8 @@ void ComputeTempPartial::compute_vector() { int i; + invoked |= INVOKED_VECTOR; + double **v = atom->v; double *mass = atom->mass; double *rmass = atom->rmass; diff --git a/src/compute_temp_ramp.cpp b/src/compute_temp_ramp.cpp index f0bb271ebb..6c7663472b 100644 --- a/src/compute_temp_ramp.cpp +++ b/src/compute_temp_ramp.cpp @@ -29,6 +29,9 @@ using namespace LAMMPS_NS; #define MIN(A,B) ((A) < (B)) ? (A) : (B) #define MAX(A,B) ((A) > (B)) ? (A) : (B) +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 + /* ---------------------------------------------------------------------- */ ComputeTempRamp::ComputeTempRamp(LAMMPS *lmp, int narg, char **arg) : @@ -101,7 +104,8 @@ ComputeTempRamp::ComputeTempRamp(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; tempflag = 1; vector = new double[6]; @@ -141,6 +145,8 @@ double ComputeTempRamp::compute_scalar() { double fraction,vramp,vthermal[3]; + invoked |= INVOKED_SCALAR; + double **x = atom->x; double **v = atom->v; double *mass = atom->mass; @@ -181,6 +187,8 @@ void ComputeTempRamp::compute_vector() int i; double fraction,vramp,vthermal[3]; + invoked |= INVOKED_VECTOR; + double **x = atom->x; double **v = atom->v; double *mass = atom->mass; diff --git a/src/compute_temp_region.cpp b/src/compute_temp_region.cpp index 0253187004..aeaad13877 100644 --- a/src/compute_temp_region.cpp +++ b/src/compute_temp_region.cpp @@ -22,6 +22,9 @@ using namespace LAMMPS_NS; +#define INVOKED_SCALAR 1 +#define INVOKED_VECTOR 2 + /* ---------------------------------------------------------------------- */ ComputeTempRegion::ComputeTempRegion(LAMMPS *lmp, int narg, char **arg) : @@ -34,7 +37,8 @@ ComputeTempRegion::ComputeTempRegion(LAMMPS *lmp, int narg, char **arg) : scalar_flag = vector_flag = 1; size_vector = 6; - extensive = 0; + extscalar = 0; + extvector = 1; tempflag = 1; vector = new double[6]; @@ -58,6 +62,8 @@ void ComputeTempRegion::init() double ComputeTempRegion::compute_scalar() { + invoked |= INVOKED_SCALAR; + double **x = atom->x; double **v = atom->v; double *mass = atom->mass; @@ -102,6 +108,8 @@ void ComputeTempRegion::compute_vector() { int i; + invoked |= INVOKED_VECTOR; + double **x = atom->x; double **v = atom->v; double *mass = atom->mass; diff --git a/src/compute_variable.cpp b/src/compute_variable.cpp deleted file mode 100644 index edde51dddb..0000000000 --- a/src/compute_variable.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#include "mpi.h" -#include "string.h" -#include "stdlib.h" -#include "compute_variable.h" -#include "input.h" -#include "variable.h" -#include "error.h" - -using namespace LAMMPS_NS; - -/* ---------------------------------------------------------------------- */ - -ComputeVariable::ComputeVariable(LAMMPS *lmp, int narg, char **arg) : - Compute(lmp, narg, arg) -{ - if (narg != 4) error->all("Illegal compute variable command"); - - // store variable name - - int n = strlen(arg[3]) + 1; - varname = new char[n]; - strcpy(varname,arg[3]); - - scalar_flag = 1; - extensive = 0; -} - -/* ---------------------------------------------------------------------- */ - -ComputeVariable::~ComputeVariable() -{ - delete [] varname; -} - -/* ---------------------------------------------------------------------- */ - -void ComputeVariable::init() -{ - // check if variable exists - - int ivariable = input->variable->find(varname); - if (ivariable < 0) - error->all("Could not find compute variable name"); -} - -/* ---------------------------------------------------------------------- */ - -double ComputeVariable::compute_scalar() -{ - scalar = atof(input->variable->retrieve(varname)); - return scalar; -} diff --git a/src/compute_variable.h b/src/compute_variable.h deleted file mode 100644 index 1f48d3b5de..0000000000 --- a/src/compute_variable.h +++ /dev/null @@ -1,34 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifndef COMPUTE_VARIABLE_H -#define COMPUTE_VARIABLE_H - -#include "compute.h" - -namespace LAMMPS_NS { - -class ComputeVariable : public Compute { - public: - ComputeVariable(class LAMMPS *, int, char **); - ~ComputeVariable(); - void init(); - double compute_scalar(); - - private: - char *varname; -}; - -} - -#endif diff --git a/src/compute_variable_atom.cpp b/src/compute_variable_atom.cpp deleted file mode 100644 index a37bbdb915..0000000000 --- a/src/compute_variable_atom.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#include "string.h" -#include "compute_variable_atom.h" -#include "atom.h" -#include "input.h" -#include "variable.h" -#include "memory.h" -#include "error.h" - -using namespace LAMMPS_NS; - -/* ---------------------------------------------------------------------- */ - -ComputeVariableAtom::ComputeVariableAtom(LAMMPS *lmp, int narg, char **arg) : - Compute(lmp, narg, arg) -{ - if (narg != 4) error->all("Illegal compute variable/atom command"); - - // store variable name - - int n = strlen(arg[3]) + 1; - varname = new char[n]; - strcpy(varname,arg[3]); - - peratom_flag = 1; - size_peratom = 0; - - nmax = 0; - result = NULL; -} - -/* ---------------------------------------------------------------------- */ - -ComputeVariableAtom::~ComputeVariableAtom() -{ - delete [] varname; - memory->sfree(result); -} - -/* ---------------------------------------------------------------------- */ - -void ComputeVariableAtom::init() -{ - // set ivariable used by this compute and check if it exists - - ivariable = input->variable->find(varname); - if (ivariable < 0) - error->all("Could not find compute variable name"); -} - -/* ---------------------------------------------------------------------- */ - -void ComputeVariableAtom::compute_peratom() -{ - // grow result array if necessary - - if (atom->nlocal > nmax) { - memory->sfree(result); - nmax = atom->nmax; - result = (double *) memory->smalloc(nmax*sizeof(double), - "compute/variable/atom:result"); - scalar_atom = result; - } - - // parse variable once to create parse tree - // evaluate tree for all atoms, will be zero for atoms not in group - // free parse tree memory stored by Variable - - input->variable->build_parse_tree(ivariable); - input->variable->evaluate_parse_tree(igroup,result); - input->variable->free_parse_tree(); -} - -/* ---------------------------------------------------------------------- - memory usage of local atom-based array -------------------------------------------------------------------------- */ - -double ComputeVariableAtom::memory_usage() -{ - double bytes = nmax * sizeof(double); - return bytes; -} diff --git a/src/compute_variable_atom.h b/src/compute_variable_atom.h deleted file mode 100644 index f81db0a676..0000000000 --- a/src/compute_variable_atom.h +++ /dev/null @@ -1,37 +0,0 @@ -/* ---------------------------------------------------------------------- - LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator - http://lammps.sandia.gov, Sandia National Laboratories - Steve Plimpton, sjplimp@sandia.gov - - Copyright (2003) Sandia Corporation. Under the terms of Contract - DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains - certain rights in this software. This software is distributed under - the GNU General Public License. - - See the README file in the top-level LAMMPS directory. -------------------------------------------------------------------------- */ - -#ifndef COMPUTE_VARIABLE_ATOM_H -#define COMPUTE_VARIABLE_ATOM_H - -#include "compute.h" - -namespace LAMMPS_NS { - -class ComputeVariableAtom : public Compute { - public: - ComputeVariableAtom(class LAMMPS *, int, char **); - ~ComputeVariableAtom(); - void init(); - void compute_peratom(); - double memory_usage(); - - private: - int nmax,ivariable; - char *varname; - double *result; -}; - -} - -#endif diff --git a/src/dump_custom.cpp b/src/dump_custom.cpp index de39f86f04..8f6d46dc28 100644 --- a/src/dump_custom.cpp +++ b/src/dump_custom.cpp @@ -40,6 +40,8 @@ enum{TAG,MOL,TYPE,X,Y,Z,XS,YS,ZS,XU,YU,ZU,IX,IY,IZ, enum{LT,LE,GT,GE,EQ,NEQ}; enum{INT,DOUBLE}; +#define INVOKED_PERATOM 4 // same as in computes + /* ---------------------------------------------------------------------- */ DumpCustom::DumpCustom(LAMMPS *lmp, int narg, char **arg) : @@ -247,7 +249,7 @@ int DumpCustom::count() { int i; - // grow choose and variable storage arrays if needed + // grow choose and variable vbuf arrays if needed int nlocal = atom->nlocal; if (nlocal > maxlocal) { @@ -267,22 +269,19 @@ int DumpCustom::count() } // invoke Computes for per-atom dump quantities + // only if not already invoked if (ncompute) - for (i = 0; i < ncompute; i++) compute[i]->compute_peratom(); + for (i = 0; i < ncompute; i++) + if (!(compute[i]->invoked & INVOKED_PERATOM)) + compute[i]->compute_peratom(); - // invoke Variables for per-atom dump quantities - // parse variable once to create parse tree - // evaluate tree for all atoms, will be zero for atoms not in group - // free parse tree memory stored by Variable + // evaluate atom-style Variables for per-atom dump quantities if (nvariable) - for (i = 0; i < nvariable; i++) { - input->variable->build_parse_tree(variable[i]); - input->variable->evaluate_parse_tree(igroup,vbuf[i]); - input->variable->free_parse_tree(); - } - + for (i = 0; i < nvariable; i++) + input->variable->compute_atom(variable[i],igroup,vbuf[i],1,0); + // choose all local atoms for output for (i = 0; i < nlocal; i++) choose[i] = 1; @@ -722,7 +721,6 @@ void DumpCustom::parse_fields(int narg, char **arg) // compute value = c_ID // if no trailing [], then arg is set to 0, else arg is between [] - // if Compute has pre-computes, first add them to list } else if (strncmp(arg[iarg],"c_",2) == 0) { pack_choice[i] = &DumpCustom::pack_compute; @@ -752,9 +750,6 @@ void DumpCustom::parse_fields(int narg, char **arg) argindex[i] > modify->compute[n]->size_peratom) error->all("Dump custom compute ID vector is not large enough"); - if (modify->compute[n]->npre) - for (int ic = 0; ic < modify->compute[n]->npre; ic++) - int tmp = add_compute(modify->compute[n]->id_pre[ic]); field2index[i] = add_compute(suffix); delete [] suffix; @@ -806,8 +801,8 @@ void DumpCustom::parse_fields(int narg, char **arg) n = input->variable->find(suffix); if (n < 0) error->all("Could not find dump custom variable name"); - if (input->variable->peratom(n) == 0) - error->all("Dump custom variable does not compute peratom info"); + if (input->variable->atomstyle(n) == 0) + error->all("Dump custom variable is not atom-style variable"); field2index[i] = add_variable(suffix); delete [] suffix; @@ -983,7 +978,6 @@ int DumpCustom::modify_param(int narg, char **arg) // compute value = c_ID // if no trailing [], then arg is set to 0, else arg is between [] // must grow field2index and argindex arrays, since access is beyond nfield - // if Compute has pre-computes, first add them to list else if (strncmp(arg[1],"c_",2) == 0) { thresh_array[nthresh] = COMPUTE; @@ -1020,9 +1014,6 @@ int DumpCustom::modify_param(int narg, char **arg) argindex[nfield+nthresh] > modify->compute[n]->size_peratom) error->all("Dump custom compute ID vector is not large enough"); - if (modify->compute[n]->npre) - for (int ic = 0; ic < modify->compute[n]->npre; ic++) - int tmp = add_compute(modify->compute[n]->id_pre[ic]); field2index[nfield+nthresh] = add_compute(suffix); delete [] suffix; @@ -1087,8 +1078,8 @@ int DumpCustom::modify_param(int narg, char **arg) n = input->variable->find(suffix); if (n < 0) error->all("Could not find dump custom variable name"); - if (input->variable->peratom(n) == 0) - error->all("Dump custom variable does not compute peratom info"); + if (input->variable->atomstyle(n) == 0) + error->all("Dump custom variable is not atom-style variable"); field2index[nfield+nthresh] = add_variable(suffix); delete [] suffix; @@ -1129,11 +1120,80 @@ double DumpCustom::memory_usage() return bytes; } -// ---------------------------------------------------------------------- -// one method for every keyword dump custom can output -// the atom quantity is packed into buf starting at n with stride size_one -// customize by adding a method -// ---------------------------------------------------------------------- +/* ---------------------------------------------------------------------- + extraction of Compute, Fix, Variable results +------------------------------------------------------------------------- */ + +void DumpCustom::pack_compute(int n) +{ + double *vector = compute[field2index[n]]->scalar_atom; + double **array = compute[field2index[n]]->vector_atom; + int index = argindex[n]; + + int nlocal = atom->nlocal; + + if (index == 0) { + for (int i = 0; i < nlocal; i++) + if (choose[i]) { + buf[n] = vector[i]; + n += size_one; + } + } else { + index--; + for (int i = 0; i < nlocal; i++) + if (choose[i]) { + buf[n] = array[i][index]; + n += size_one; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpCustom::pack_fix(int n) +{ + double *vector = fix[field2index[n]]->scalar_atom; + double **array = fix[field2index[n]]->vector_atom; + int index = argindex[n]; + + int nlocal = atom->nlocal; + + if (index == 0) { + for (int i = 0; i < nlocal; i++) + if (choose[i]) { + buf[n] = vector[i]; + n += size_one; + } + } else { + index--; + for (int i = 0; i < nlocal; i++) + if (choose[i]) { + buf[n] = array[i][index]; + n += size_one; + } + } +} + +/* ---------------------------------------------------------------------- */ + +void DumpCustom::pack_variable(int n) +{ + double *vector = vbuf[field2index[n]]; + + int nlocal = atom->nlocal; + + for (int i = 0; i < nlocal; i++) + if (choose[i]) { + buf[n] = vector[i]; + n += size_one; + } +} + +/* ---------------------------------------------------------------------- + one method for every keyword dump custom can output + the atom quantity is packed into buf starting at n with stride size_one + customize a new keyword by adding a method +------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ @@ -1597,70 +1657,3 @@ void DumpCustom::pack_tqz(int n) n += size_one; } } - -/* ---------------------------------------------------------------------- */ - -void DumpCustom::pack_compute(int n) -{ - double *vector = compute[field2index[n]]->scalar_atom; - double **array = compute[field2index[n]]->vector_atom; - int index = argindex[n]; - - int nlocal = atom->nlocal; - - if (index == 0) { - for (int i = 0; i < nlocal; i++) - if (choose[i]) { - buf[n] = vector[i]; - n += size_one; - } - } else { - index--; - for (int i = 0; i < nlocal; i++) - if (choose[i]) { - buf[n] = array[i][index]; - n += size_one; - } - } -} - -/* ---------------------------------------------------------------------- */ - -void DumpCustom::pack_fix(int n) -{ - double *vector = fix[field2index[n]]->scalar_atom; - double **array = fix[field2index[n]]->vector_atom; - int index = argindex[n]; - - int nlocal = atom->nlocal; - - if (index == 0) { - for (int i = 0; i < nlocal; i++) - if (choose[i]) { - buf[n] = vector[i]; - n += size_one; - } - } else { - index--; - for (int i = 0; i < nlocal; i++) - if (choose[i]) { - buf[n] = array[i][index]; - n += size_one; - } - } -} - -/* ---------------------------------------------------------------------- */ - -void DumpCustom::pack_variable(int n) -{ - double *vector = vbuf[field2index[n]]; - - int nlocal = atom->nlocal; - - for (int i = 0; i < nlocal; i++) - if (choose[i]) { - buf[n] = vector[i]; - n += size_one; - } -} diff --git a/src/fix.cpp b/src/fix.cpp index 566f1819d1..dafb55c21c 100644 --- a/src/fix.cpp +++ b/src/fix.cpp @@ -12,6 +12,7 @@ ------------------------------------------------------------------------- */ #include "string.h" +#include "ctype.h" #include "fix.h" #include "group.h" #include "error.h" @@ -22,11 +23,19 @@ using namespace LAMMPS_NS; Fix::Fix(LAMMPS *lmp, int narg, char **arg) : Pointers(lmp) { + // fix ID, group, and style + // ID must be all alphanumeric chars or underscores + int n = strlen(arg[0]) + 1; id = new char[n]; strcpy(id,arg[0]); + for (int i = 0; i < n-1; i++) + if (!isalnum(id[i]) && id[i] != '_') + error->all("Fix ID must be alphanumeric or underscore characters"); + igroup = group->find(arg[1]); + if (igroup == -1) error->all("Could not find fix group ID"); groupbit = group->bitmask[igroup]; n = strlen(arg[2]) + 1; diff --git a/src/fix.h b/src/fix.h index c798bb3bc5..754daf3c4c 100644 --- a/src/fix.h +++ b/src/fix.h @@ -38,7 +38,9 @@ class Fix : protected Pointers { int vector_flag; // 0/1 if compute_vector() function exists int size_vector; // N = size of global vector int scalar_vector_freq; // frequency compute s/v data is available at - int extensive; // 0/1 if s/v are intensive/extensive values + int extscalar; // 0/1 if scalar is intensive/extensive + int extvector; // 0/1/-1 if vector is all int/ext/extlist + int *extlist; // list of 0/1 int/ext for each vec component int peratom_flag; // 0/1 if per-atom data is stored int size_peratom; // 0 = scalar_atom, N = size of vector_atom diff --git a/src/fix_ave_atom.cpp b/src/fix_ave_atom.cpp index 9295a7ad4c..bb320105c8 100644 --- a/src/fix_ave_atom.cpp +++ b/src/fix_ave_atom.cpp @@ -18,25 +18,99 @@ #include "update.h" #include "modify.h" #include "compute.h" +#include "input.h" +#include "variable.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; +enum{X,V,F,COMPUTE,FIX,VARIABLE}; + +#define INVOKED_PERATOM 4 // same as in computes + /* ---------------------------------------------------------------------- */ FixAveAtom::FixAveAtom(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { - if (narg != 7) error->all("Illegal fix ave/atom command"); + if (narg < 7) error->all("Illegal fix ave/atom command"); nevery = atoi(arg[3]); nrepeat = atoi(arg[4]); peratom_freq = atoi(arg[5]); - int n = strlen(arg[6]) + 1; - id_compute = new char[n]; - strcpy(id_compute,arg[6]); + // parse remaining values + + which = new int[narg-6]; + argindex = new int[narg-6]; + ids = new char*[narg-6]; + value2index = new int[narg-6]; + nvalues = 0; + + int iarg = 6; + while (iarg < narg) { + ids[nvalues] = NULL; + + if (strcmp(arg[iarg],"x") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"y") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"z") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 2; + + } else if (strcmp(arg[iarg],"vx") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"vy") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"vz") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 2; + + } else if (strcmp(arg[iarg],"fx") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"fy") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"fz") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 2; + + } else if ((strncmp(arg[iarg],"c_",2) == 0) || + (strncmp(arg[iarg],"f_",2) == 0) || + (strncmp(arg[iarg],"v_",2) == 0)) { + if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE; + else if (arg[iarg][0] == 'f') which[nvalues] = FIX; + else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE; + + int n = strlen(arg[iarg]); + char *suffix = new char[n]; + strcpy(suffix,&arg[iarg][2]); + + char *ptr = strchr(suffix,'['); + if (ptr) { + if (suffix[strlen(suffix)-1] != ']') + error->all("Illegal fix ave/atom command"); + argindex[nvalues] = atoi(ptr+1); + *ptr = '\0'; + } else argindex[nvalues] = 0; + + n = strlen(suffix) + 1; + ids[nvalues] = new char[n]; + strcpy(ids[nvalues],suffix); + nvalues++; + delete [] suffix; + + } else error->all("Illegal fix ave/atom command"); + + iarg++; + } // setup and error check @@ -45,24 +119,49 @@ FixAveAtom::FixAveAtom(LAMMPS *lmp, int narg, char **arg) : (nrepeat-1)*nevery >= peratom_freq) error->all("Illegal fix ave/atom command"); - int icompute = modify->find_compute(id_compute); - if (icompute < 0) error->all("Compute ID for fix ave/atom does not exist"); + for (int i = 0; i < nvalues; i++) { + if (which[i] == COMPUTE) { + int icompute = modify->find_compute(ids[i]); + if (icompute < 0) + error->all("Compute ID for fix ave/atom does not exist"); + if (modify->compute[icompute]->peratom_flag == 0) + error->all("Fix ave/atom compute does not calculate per-atom values"); + if (argindex[i] == 0 && modify->compute[icompute]->size_peratom != 0) + error->all("Fix ave/atom compute does not calculate a per-atom scalar"); + if (argindex[i] && modify->compute[icompute]->size_peratom == 0) + error->all("Fix ave/atom compute does not calculate a per-atom vector"); + if (argindex[i] && argindex[i] > modify->compute[icompute]->size_peratom) + error->all("Fix ave/atom compute vector is accessed out-of-range"); + } else if (which[i] == FIX) { + int ifix = modify->find_fix(ids[i]); + if (ifix < 0) + error->all("Fix ID for fix ave/atom does not exist"); + if (modify->fix[ifix]->peratom_flag == 0) + error->all("Fix ave/atom fix does not calculate per-atom values"); + if (argindex[i] && modify->fix[ifix]->size_peratom != 0) + error->all("Fix ave/atom fix does not calculate a per-atom scalar"); + if (argindex[i] && modify->fix[ifix]->size_peratom == 0) + error->all("Fix ave/atom fix does not calculate a per-atom vector"); + if (argindex[i] && argindex[i] > modify->fix[ifix]->size_peratom) + error->all("Fix ave/atom fix vector is accessed out-of-range"); + } else if (which[i] == VARIABLE) { + int ivariable = input->variable->find(ids[i]); + if (ivariable < 0) + error->all("Variable name for fix ave/atom does not exist"); + if (input->variable->atomstyle(ivariable) == 0) + error->all("Fix ave/atom variable is not atom-style variable"); + } + } - if (modify->compute[icompute]->peratom_flag == 0) - error->all("Fix ave/atom compute does not calculate per-atom info"); + // this fix produces either a per-atom scalar or vector peratom_flag = 1; - - // setup list of computes to call, including pre-computes - - ncompute = 1 + modify->compute[icompute]->npre; - compute = new Compute*[ncompute]; + if (nvalues == 1) size_peratom = 0; + else size_peratom = nvalues; // perform initial allocation of atom-based array // register with Atom class - size_peratom = modify->compute[icompute]->size_peratom; - scalar = NULL; vector = NULL; grow_arrays(atom->nmax); atom->add_callback(0); @@ -70,13 +169,10 @@ FixAveAtom::FixAveAtom(LAMMPS *lmp, int narg, char **arg) : // zero the array since dump may access it on timestep 0 int nlocal = atom->nlocal; - if (size_peratom == 0) - for (int i = 0; i < nlocal; i++) scalar[i] = 0.0; - else - for (int i = 0; i < nlocal; i++) - for (int m = 0; m < size_peratom; m++) - vector[i][m] = 0.0; - + for (int i = 0; i < nlocal; i++) + for (int m = 0; m < nvalues; m++) + vector[i][m] = 0.0; + // nvalid = next step on which end_of_step does something // can be this timestep if multiple of peratom_freq and nrepeat = 1 // else backup from next multiple of peratom_freq @@ -89,12 +185,11 @@ FixAveAtom::FixAveAtom(LAMMPS *lmp, int narg, char **arg) : nvalid -= (nrepeat-1)*nevery; if (nvalid < update->ntimestep) nvalid += peratom_freq; - // set timestep for all computes that store invocation times - // since don't know a priori which are invoked by this fix + // add nvalid to ALL computes that store invocation times + // since don't know a priori which are invoked by this fix // once in end_of_step() can just set timestep for ones actually invoked - for (int i = 0; i < modify->ncompute; i++) - if (modify->compute[i]->timeflag) modify->compute[i]->add_step(nvalid); + modify->addstep_compute_all(nvalid); } /* ---------------------------------------------------------------------- */ @@ -105,9 +200,12 @@ FixAveAtom::~FixAveAtom() atom->delete_callback(id,0); - delete [] id_compute; - delete [] compute; - memory->sfree(scalar); + delete [] which; + delete [] argindex; + for (int m = 0; m < nvalues; m++) delete [] ids[m]; + delete [] ids; + delete [] value2index; + memory->destroy_2d_double_array(vector); } @@ -124,29 +222,49 @@ int FixAveAtom::setmask() void FixAveAtom::init() { - // set ptrs to compute and its pre-computes called each end-of-step - // put pre-computes in list before compute + // set indices and check validity of all computes,fixes,variables + // check that fix frequency is acceptable - int icompute = modify->find_compute(id_compute); - if (icompute < 0) error->all("Compute ID for fix ave/atom does not exist"); - - ncompute = 0; - if (modify->compute[icompute]->npre) - for (int i = 0; i < modify->compute[icompute]->npre; i++) { - int ic = modify->find_compute(modify->compute[icompute]->id_pre[i]); - if (ic < 0) - error->all("Precompute ID of compute for fix ave/atom does not exist"); - compute[ncompute++] = modify->compute[ic]; - } + for (int m = 0; m < nvalues; m++) { + if (which[m] == COMPUTE) { + int icompute = modify->find_compute(ids[m]); + if (icompute < 0) + error->all("Compute ID for fix ave/atom does not exist"); + value2index[m] = icompute; + + } else if (which[m] == FIX) { + int ifix = modify->find_fix(ids[m]); + if (ifix < 0) + error->all("Fix ID for fix ave/atom does not exist"); + value2index[m] = ifix; - compute[ncompute++] = modify->compute[icompute]; + if (nevery % modify->fix[ifix]->peratom_freq) + error->all("Fix for fix ave/atom not computed at compatible time"); + + } else if (which[m] == VARIABLE) { + int ivariable = input->variable->find(ids[m]); + if (ivariable < 0) + error->all("Variable name for fix ave/atom does not exist"); + value2index[m] = ivariable; + + } else value2index[m] = -1; + } +} + +/* ---------------------------------------------------------------------- + only does something if nvalid = current timestep +------------------------------------------------------------------------- */ + +void FixAveAtom::setup() +{ + end_of_step(); } /* ---------------------------------------------------------------------- */ void FixAveAtom::end_of_step() { - int i,m; + int i,j,m,n; // skip if not step which requires doing something @@ -156,32 +274,70 @@ void FixAveAtom::end_of_step() int nlocal = atom->nlocal; - if (irepeat == 0) { - if (size_peratom == 0) - for (i = 0; i < nlocal; i++) scalar[i] = 0.0; - else - for (i = 0; i < nlocal; i++) - for (m = 0; m < size_peratom; m++) - vector[i][m] = 0.0; - } - - // accumulate results of compute to local copy + if (irepeat == 0) + for (i = 0; i < nlocal; i++) + for (m = 0; m < nvalues; m++) + vector[i][m] = 0.0; + // accumulate results of attributes,computes,fixes,variables to local copy + // compute/fix/variable may invoke computes so wrap with clear/add + modify->clearstep_compute(); - for (i = 0; i < ncompute; i++) compute[i]->compute_peratom(); - + int *mask = atom->mask; - if (size_peratom == 0) { - double *compute_scalar = compute[ncompute-1]->scalar_atom; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) scalar[i] += compute_scalar[i]; - } else { - double **compute_vector = compute[ncompute-1]->vector_atom; - for (i = 0; i < nlocal; i++) - if (mask[i] & groupbit) - for (m = 0; m < size_peratom; m++) - vector[i][m] += compute_vector[i][m]; + for (m = 0; m < nvalues; m++) { + n = value2index[m]; + j = argindex[m]; + + if (which[m] == X) { + double **x = atom->x; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) vector[i][m] += x[i][j]; + } else if (which[m] == V) { + double **v = atom->v; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) vector[i][m] += v[i][j]; + } else if (which[m] == F) { + double **f = atom->f; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) vector[i][m] += f[i][j]; + + // invoke compute if not previously invoked + + } else if (which[m] == COMPUTE) { + Compute *compute = modify->compute[n]; + if (!(compute->invoked & INVOKED_PERATOM)) compute->compute_peratom(); + + if (j == 0) { + double *compute_scalar = compute->scalar_atom; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) vector[i][m] += compute_scalar[i]; + } else { + int jm1 = j - 1; + double **compute_vector = compute->vector_atom; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) vector[i][m] += compute_vector[i][jm1]; + } + + // access fix fields, guaranteed to be ready + + } else if (which[m] == FIX) { + if (j == 0) { + double *fix_scalar = modify->fix[n]->scalar_atom; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) vector[i][m] += fix_scalar[i]; + } else { + int jm1 = j - 1; + double **fix_vector = modify->fix[n]->vector_atom; + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) vector[i][m] += fix_vector[i][jm1]; + } + + // evaluate atom-style variable + + } else if (which[m] == VARIABLE) + input->variable->compute_atom(n,igroup,&vector[0][m],nvalues,1); } // done if irepeat < nrepeat @@ -201,13 +357,9 @@ void FixAveAtom::end_of_step() // average the final result for the Nfreq timestep double repeat = nrepeat; - if (size_peratom == 0) - for (i = 0; i < nlocal; i++) - scalar[i] /= repeat; - else - for (i = 0; i < nlocal; i++) - for (m = 0; m < size_peratom; m++) - vector[i][m] /= repeat; + for (i = 0; i < nlocal; i++) + for (m = 0; m < nvalues; m++) + vector[i][m] /= repeat; } /* ---------------------------------------------------------------------- @@ -217,8 +369,7 @@ void FixAveAtom::end_of_step() double FixAveAtom::memory_usage() { double bytes; - if (size_peratom == 0) bytes = atom->nmax * sizeof(double); - else bytes = atom->nmax*size_peratom * sizeof(double); + bytes = atom->nmax*nvalues * sizeof(double); return bytes; } @@ -228,15 +379,10 @@ double FixAveAtom::memory_usage() void FixAveAtom::grow_arrays(int nmax) { - if (size_peratom == 0) { - scalar = (double *) memory->srealloc(scalar,nmax*sizeof(double), - "fix_ave/atom:scalar"); - scalar_atom = scalar; - } else { - vector = memory->grow_2d_double_array(vector,nmax,size_peratom, - "fix_ave/atom:vector"); - vector_atom = vector; - } + vector = memory->grow_2d_double_array(vector,nmax,nvalues, + "fix_ave/atom:vector"); + vector_atom = vector; + scalar_atom = vector[0]; } /* ---------------------------------------------------------------------- @@ -245,11 +391,8 @@ void FixAveAtom::grow_arrays(int nmax) void FixAveAtom::copy_arrays(int i, int j) { - if (size_peratom == 0) - scalar[j] = scalar[i]; - else - for (int m = 0; m <= size_peratom; m++) - vector[j][m] = vector[i][m]; + for (int m = 0; m < nvalues; m++) + vector[j][m] = vector[i][m]; } /* ---------------------------------------------------------------------- @@ -258,13 +401,8 @@ void FixAveAtom::copy_arrays(int i, int j) int FixAveAtom::pack_exchange(int i, double *buf) { - if (size_peratom == 0) { - buf[0] = scalar[i]; - return 1; - } - - for (int m = 0; m <= size_peratom; m++) buf[m] = vector[i][m]; - return size_peratom; + for (int m = 0; m < nvalues; m++) buf[m] = vector[i][m]; + return nvalues; } /* ---------------------------------------------------------------------- @@ -273,11 +411,6 @@ int FixAveAtom::pack_exchange(int i, double *buf) int FixAveAtom::unpack_exchange(int nlocal, double *buf) { - if (size_peratom == 0) { - scalar[nlocal] = buf[0]; - return 1; - } - - for (int m = 0; m <= size_peratom; m++) vector[nlocal][m] = buf[m]; - return size_peratom; + for (int m = 0; m < nvalues; m++) vector[nlocal][m] = buf[m]; + return nvalues; } diff --git a/src/fix_ave_atom.h b/src/fix_ave_atom.h index 8ded424601..e2f47a417c 100644 --- a/src/fix_ave_atom.h +++ b/src/fix_ave_atom.h @@ -25,6 +25,7 @@ class FixAveAtom : public Fix { ~FixAveAtom(); int setmask(); void init(); + void setup(); void end_of_step(); double memory_usage(); @@ -34,12 +35,11 @@ class FixAveAtom : public Fix { int unpack_exchange(int, double *); private: - int nrepeat,irepeat,nvalid; - char *id_compute; - int ncompute; - class Compute **compute; + int nvalues; + int nrepeat,nvalid,irepeat; + int *which,*argindex,*value2index; + char **ids; - double *scalar; double **vector; }; diff --git a/src/fix_ave_spatial.cpp b/src/fix_ave_spatial.cpp index 0305213a49..093e6ed573 100644 --- a/src/fix_ave_spatial.cpp +++ b/src/fix_ave_spatial.cpp @@ -24,26 +24,28 @@ #include "lattice.h" #include "modify.h" #include "compute.h" -#include "group.h" +#include "input.h" +#include "variable.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; enum{LOWER,CENTER,UPPER,COORD}; -enum{DENSITY_MASS,DENSITY_NUM,COMPUTE,FIX}; +enum{X,V,F,DENSITY_NUMBER,DENSITY_MASS,COMPUTE,FIX,VARIABLE}; enum{SAMPLE,ALL}; enum{BOX,LATTICE,REDUCED}; enum{ONE,RUNNING,WINDOW}; #define BIG 1000000000 +#define INVOKED_PERATOM 4 // same as in computes /* ---------------------------------------------------------------------- */ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { - if (narg < 11) error->all("Illegal fix ave/spatial command"); + if (narg < 10) error->all("Illegal fix ave/spatial command"); MPI_Comm_rank(world,&me); @@ -62,34 +64,96 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) : if (strcmp(arg[7],"center") == 0) originflag = CENTER; if (strcmp(arg[7],"upper") == 0) originflag = UPPER; else originflag = COORD; - if (originflag == COORD) origin = atof(arg[6]); + if (originflag == COORD) origin = atof(arg[7]); delta = atof(arg[8]); - if (strcmp(arg[9],"density") == 0) { - if (strcmp(arg[10],"mass") == 0) which = DENSITY_MASS; - else if (strcmp(arg[10],"number") == 0) which = DENSITY_NUM; - else error->all("Illegal fix ave/spatial command"); - } else if (strcmp(arg[9],"compute") == 0) { - which = COMPUTE; - int n = strlen(arg[10]) + 1; - id_compute = new char[n]; - strcpy(id_compute,arg[10]); - } else if (strcmp(arg[9],"fix") == 0) { - which = FIX; - int n = strlen(arg[10]) + 1; - id_fix = new char[n]; - strcpy(id_fix,arg[10]); - } else error->all("Illegal fix ave/spatial command"); + // parse values until one isn't recognized - // parse optional args + which = new int[narg-9]; + argindex = new int[narg-9]; + ids = new char*[narg-9]; + value2index = new int[narg-9]; + nvalues = 0; + + int iarg = 9; + while (iarg < narg) { + ids[nvalues] = NULL; + + if (strcmp(arg[iarg],"x") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"y") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"z") == 0) { + which[nvalues] = X; + argindex[nvalues++] = 2; + + } else if (strcmp(arg[iarg],"vx") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"vy") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"vz") == 0) { + which[nvalues] = V; + argindex[nvalues++] = 2; + + } else if (strcmp(arg[iarg],"fx") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"fy") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 1; + } else if (strcmp(arg[iarg],"fz") == 0) { + which[nvalues] = F; + argindex[nvalues++] = 2; + + } else if (strcmp(arg[iarg],"density/number") == 0) { + which[nvalues] = DENSITY_NUMBER; + argindex[nvalues++] = 0; + } else if (strcmp(arg[iarg],"density/mass") == 0) { + which[nvalues] = DENSITY_MASS; + argindex[nvalues++] = 0; + + } else if ((strncmp(arg[iarg],"c_",2) == 0) || + (strncmp(arg[iarg],"f_",2) == 0) || + (strncmp(arg[iarg],"v_",2) == 0)) { + if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE; + else if (arg[iarg][0] == 'f') which[nvalues] = FIX; + else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE; + + int n = strlen(arg[iarg]); + char *suffix = new char[n]; + strcpy(suffix,&arg[iarg][2]); + + char *ptr = strchr(suffix,'['); + if (ptr) { + if (suffix[strlen(suffix)-1] != ']') + error->all("Illegal fix ave/spatial command"); + argindex[nvalues] = atoi(ptr+1); + *ptr = '\0'; + } else argindex[nvalues] = 0; + + n = strlen(suffix) + 1; + ids[nvalues] = new char[n]; + strcpy(ids[nvalues],suffix); + nvalues++; + delete [] suffix; + + } else break; + + iarg++; + } + + // optional args normflag = ALL; scaleflag = BOX; fp = NULL; ave = ONE; - int iarg = 11; while (iarg < narg) { if (strcmp(arg[iarg],"norm") == 0) { if (iarg+2 > narg) error->all("Illegal fix ave/spatial command"); @@ -131,11 +195,71 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) : } else error->all("Illegal fix ave/spatial command"); } - // if density, no normalization by atom count should be done - // thus ALL and SAMPLE should give same answer, but code does normalize - // thus only ALL is computed correctly, so force norm to be ALL + // setup and error check - if (which == DENSITY_MASS || which == DENSITY_NUM) normflag = ALL; + if (nevery <= 0) error->all("Illegal fix ave/spatial command"); + if (nfreq < nevery || nfreq % nevery || (nrepeat-1)*nevery >= nfreq) + error->all("Illegal fix ave/spatial command"); + + if (delta <= 0.0) error->all("Illegal fix ave/spatial command"); + invdelta = 1.0/delta; + + for (int i = 0; i < nvalues; i++) { + if (which[i] == COMPUTE) { + int icompute = modify->find_compute(ids[i]); + if (icompute < 0) + error->all("Compute ID for fix ave/spatial does not exist"); + if (modify->compute[icompute]->peratom_flag == 0) + error->all("Fix ave/spatial compute does not calculate per-atom values"); + if (argindex[i] == 0 && modify->compute[icompute]->size_peratom != 0) + error->all("Fix ave/spatial compute does not calculate a per-atom scalar"); + if (argindex[i] && modify->compute[icompute]->size_peratom == 0) + error->all("Fix ave/spatial compute does not calculate a per-atom vector"); + if (argindex[i] && argindex[i] > modify->compute[icompute]->size_peratom) + error->all("Fix ave/spatial compute vector is accessed out-of-range"); + + } else if (which[i] == FIX) { + int ifix = modify->find_fix(ids[i]); + if (ifix < 0) + error->all("Fix ID for fix ave/spatial does not exist"); + if (modify->fix[ifix]->peratom_flag == 0) + error->all("Fix ave/spatial fix does not calculate per-atom values"); + if (argindex[i] && modify->fix[ifix]->size_peratom != 0) + error->all("Fix ave/spatial fix does not calculate a per-atom scalar"); + if (argindex[i] && modify->fix[ifix]->size_peratom == 0) + error->all("Fix ave/spatial fix does not calculate a per-atom vector"); + if (argindex[i] && argindex[i] > modify->fix[ifix]->size_peratom) + error->all("Fix ave/spatial fix vector is accessed out-of-range"); + } else if (which[i] == VARIABLE) { + int ivariable = input->variable->find(ids[i]); + if (ivariable < 0) + error->all("Variable name for fix ave/spatial does not exist"); + if (input->variable->atomstyle(ivariable) == 0) + error->all("Fix ave/spatial variable is not atom-style variable"); + } + } + + // print header into file + + if (fp && me == 0) { + fprintf(fp,"Spatial-averaged data for fix %s and group %s\n",id,arg[1]); + fprintf(fp,"TimeStep Number-of-layers\n"); + fprintf(fp,"Layer Coordinate Natoms"); + for (int i = 0; i < nvalues; i++) + if (which[i] == COMPUTE) fprintf(fp," c_%s",ids[i]); + else if (which[i] == FIX) fprintf(fp," f_%s",ids[i]); + else if (which[i] == VARIABLE) fprintf(fp," v_%s",ids[i]); + else fprintf(fp," %s",arg[9+i]); + fprintf(fp,"\n"); + } + + // this fix produces a global vector + // set size_vector to BIG since compute_vector() checks bounds on-the-fly + + vector_flag = 1; + size_vector = BIG; + scalar_vector_freq = nfreq; + extvector = 0; // setup scaling @@ -162,60 +286,6 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) : delta *= scale; if (originflag == COORD) origin *= scale; - // setup and error check - - if (nevery <= 0) error->all("Illegal fix ave/spatial command"); - if (nfreq < nevery || nfreq % nevery || (nrepeat-1)*nevery >= nfreq) - error->all("Illegal fix ave/spatial command"); - - if (delta <= 0.0) error->all("Illegal fix ave/spatial command"); - invdelta = 1.0/delta; - - // nvalues = # of quantites per line of output file - // for COMPUTE, setup list of computes to call, including pre-computes - - nvalues = 1; - compute = NULL; - - if (which == COMPUTE) { - int icompute = modify->find_compute(id_compute); - if (icompute < 0) - error->all("Compute ID for fix ave/spatial does not exist"); - if (modify->compute[icompute]->peratom_flag == 0) - error->all("Fix ave/spatial compute does not calculate per-atom info"); - nvalues = size_peratom = modify->compute[icompute]->size_peratom; - if (nvalues == 0) nvalues = 1; - ncompute = 1 + modify->compute[icompute]->npre; - compute = new Compute*[ncompute]; - } - - if (which == FIX) { - int ifix = modify->find_fix(id_fix); - if (ifix < 0) - error->all("Fix ID for fix ave/spatial does not exist"); - if (modify->fix[ifix]->peratom_flag == 0) - error->all("Fix ave/spatial fix does not calculate per-atom info"); - nvalues = size_peratom = modify->fix[ifix]->size_peratom; - if (nvalues == 0) nvalues = 1; - } - - // print header into file - - if (fp && me == 0) { - fprintf(fp,"Spatial-averaged data for fix %s, group %s, and %s %s\n", - id,group->names[igroup],arg[10],arg[11]); - fprintf(fp,"TimeStep Number-of-layers (one per snapshot)\n"); - fprintf(fp,"Layer Coord Atoms Value(s) (one per layer)\n"); - } - - // enable this fix to produce a global vector - // set size_vector to BIG since compute_vector() will check bounds - - vector_flag = 1; - size_vector = BIG; - scalar_vector_freq = nfreq; - extensive = 0; - // initializations irepeat = 0; @@ -228,6 +298,12 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) : values_one = values_many = values_sum = values_total = NULL; values_list = NULL; + maxatomvar = 0; + varatom = NULL; + + maxatomlayer = 0; + layer = NULL; + // nvalid = next step on which end_of_step does something // can be this timestep if multiple of nfreq and nrepeat = 1 // else backup from next multiple of nfreq @@ -239,24 +315,24 @@ FixAveSpatial::FixAveSpatial(LAMMPS *lmp, int narg, char **arg) : nvalid -= (nrepeat-1)*nevery; if (nvalid < update->ntimestep) nvalid += nfreq; - // set timestep for all computes that store invocation times - // since don't know a priori which are invoked by this fix + // add nvalid to ALL computes that store invocation times + // since don't know a priori which are invoked by this fix // once in end_of_step() can just set timestep for ones actually invoked - if (which == COMPUTE) - for (int i = 0; i < modify->ncompute; i++) - if (modify->compute[i]->timeflag) modify->compute[i]->add_step(nvalid); + modify->addstep_compute_all(nvalid); } /* ---------------------------------------------------------------------- */ FixAveSpatial::~FixAveSpatial() { - if (which == COMPUTE) delete [] id_compute; - if (which == FIX) delete [] id_fix; - if (fp && me == 0) fclose(fp); + delete [] which; + delete [] argindex; + for (int i = 0; i < nvalues; i++) delete [] ids[i]; + delete [] ids; + delete [] value2index; - delete [] compute; + if (fp && me == 0) fclose(fp); memory->sfree(coord); memory->sfree(count_one); @@ -269,6 +345,9 @@ FixAveSpatial::~FixAveSpatial() memory->destroy_2d_double_array(values_sum); memory->destroy_2d_double_array(values_total); memory->destroy_3d_double_array(values_list); + + memory->sfree(varatom); + memory->sfree(layer); } /* ---------------------------------------------------------------------- */ @@ -291,36 +370,32 @@ void FixAveSpatial::init() error->all("Fix ave/spatial settings invalid with changing box"); } - // set ptrs to compute and its pre-computes called each end-of-step - // put pre-computes in list before compute - - if (which == COMPUTE) { - int icompute = modify->find_compute(id_compute); - if (icompute < 0) - error->all("Compute ID for fix ave/spatial does not exist"); - - ncompute = 0; - if (modify->compute[icompute]->npre) - for (int i = 0; i < modify->compute[icompute]->npre; i++) { - int ic = modify->find_compute(modify->compute[icompute]->id_pre[i]); - if (ic < 0) - error->all("Precompute ID for fix ave/spatial does not exist"); - compute[ncompute++] = modify->compute[ic]; - } - - compute[ncompute++] = modify->compute[icompute]; - } - - // set ptr to fix ID + // set indices and check validity of all computes,fixes,variables // check that fix frequency is acceptable - if (which == FIX) { - int ifix = modify->find_fix(id_fix); - if (ifix < 0) - error->all("Fix ID for fix ave/spatial does not exist"); - fix = modify->fix[ifix]; - if (nevery % fix->peratom_freq) - error->all("Fix ave/spatial and fix not computed at compatible times"); + for (int m = 0; m < nvalues; m++) { + if (which[m] == COMPUTE) { + int icompute = modify->find_compute(ids[m]); + if (icompute < 0) + error->all("Compute ID for fix ave/spatial does not exist"); + value2index[m] = icompute; + + } else if (which[m] == FIX) { + int ifix = modify->find_fix(ids[m]); + if (ifix < 0) + error->all("Fix ID for fix ave/spatial does not exist"); + value2index[m] = ifix; + + if (nevery % modify->fix[ifix]->peratom_freq) + error->all("Fix for fix ave/spatial not computed at compatible time"); + + } else if (which[m] == VARIABLE) { + int ivariable = input->variable->find(ids[m]); + if (ivariable < 0) + error->all("Variable name for fix ave/spatial does not exist"); + value2index[m] = ivariable; + + } else value2index[m] = -1; } } @@ -337,7 +412,7 @@ void FixAveSpatial::setup() void FixAveSpatial::end_of_step() { - int i,j,m,ilayer; + int i,j,m,n,ilayer; double lo,hi; // skip if not step which requires doing something @@ -448,107 +523,129 @@ void FixAveSpatial::end_of_step() for (i = 0; i < nvalues; i++) values_one[m][i] = 0.0; } - // perform the computation for one sample - // sum within each layer, only include atoms in fix group + // assign each atom to a layer // insure array index is within bounds (since atoms can be outside box) - // if scaleflag = REDUCED, box coords -> lamda coords before computing layer + // if scaleflag = REDUCED, box coords -> lamda coords double **x = atom->x; int *mask = atom->mask; int nlocal = atom->nlocal; - // DENSITY_MASS adds mass to values - - if (which == DENSITY_MASS) { - int *type = atom->type; - double *mass = atom->mass; - double *rmass = atom->rmass; - - if (scaleflag == REDUCED) domain->x2lamda(nlocal); - - for (i = 0; i < nlocal; i++) { - if (mask[i] & groupbit) { - ilayer = static_cast ((x[i][dim] - offset) * invdelta); - if (ilayer < 0) ilayer = 0; - if (ilayer >= nlayers) ilayer = nlayers-1; - count_one[ilayer] += 1.0; - if (mass) values_one[ilayer][0] += mass[type[i]]; - else values_one[ilayer][0] += rmass[i]; - } - } - - if (scaleflag == REDUCED) domain->lamda2x(nlocal); - - // DENSITY_NUM adds 1 to values - - } else if (which == DENSITY_NUM) { - - if (scaleflag == REDUCED) domain->x2lamda(nlocal); - - for (i = 0; i < nlocal; i++) { - if (mask[i] & groupbit) { - ilayer = static_cast ((x[i][dim] - offset) * invdelta); - if (ilayer < 0) ilayer = 0; - if (ilayer >= nlayers) ilayer = nlayers-1; - count_one[ilayer] += 1.0; - values_one[ilayer][0] += 1.0; - } - } - - if (scaleflag == REDUCED) domain->lamda2x(nlocal); - - // COMPUTE adds its scalar or vector quantity to values - - } else if (which == COMPUTE) { - modify->clearstep_compute(); - for (i = 0; i < ncompute; i++) compute[i]->compute_peratom(); - double *scalar = compute[ncompute-1]->scalar_atom; - double **vector = compute[ncompute-1]->vector_atom; - - if (scaleflag == REDUCED) domain->x2lamda(nlocal); - - m = 0; - for (i = 0; i < nlocal; i++) { - if (mask[i] & groupbit) { - ilayer = static_cast ((x[i][dim] - offset) * invdelta); - if (ilayer < 0) ilayer = 0; - if (ilayer >= nlayers) ilayer = nlayers-1; - count_one[ilayer] += 1.0; - if (size_peratom == 0) values_one[ilayer][0] += scalar[i]; - else - for (j = 0; j < nvalues; j++) - values_one[ilayer][j] += vector[i][j]; - } - } - - if (scaleflag == REDUCED) domain->lamda2x(nlocal); - - // FIX adds its scalar or vector quantity to values - - } else if (which == FIX) { - double *scalar = fix->scalar_atom; - double **vector = fix->vector_atom; - - if (scaleflag == REDUCED) domain->x2lamda(nlocal); - - m = 0; - for (i = 0; i < nlocal; i++) { - if (mask[i] & groupbit) { - ilayer = static_cast ((x[i][dim] - offset) * invdelta); - if (ilayer < 0) ilayer = 0; - if (ilayer >= nlayers) ilayer = nlayers-1; - count_one[ilayer] += 1.0; - if (size_peratom == 0) values_one[ilayer][0] += scalar[i]; - else - for (j = 0; j < nvalues; j++) - values_one[ilayer][j] += vector[i][j]; - } - } - - if (scaleflag == REDUCED) domain->lamda2x(nlocal); + if (nlocal > maxatomlayer) { + maxatomlayer = atom->nmax; + memory->sfree(layer); + layer = (int *) + memory->smalloc(maxatomlayer*sizeof(int),"ave/spatial:layer"); } - // average a single sample + if (scaleflag == REDUCED) domain->x2lamda(nlocal); + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + ilayer = static_cast ((x[i][dim] - offset) * invdelta); + if (ilayer < 0) ilayer = 0; + if (ilayer >= nlayers) ilayer = nlayers-1; + layer[i] = ilayer; + count_one[ilayer] += 1.0; + } + + if (scaleflag == REDUCED) domain->lamda2x(nlocal); + + // perform the computation for one sample + // accumulate results of attributes,computes,fixes,variables to local copy + // sum within each layer, only include atoms in fix group + // compute/fix/variable may invoke computes so wrap with clear/add + + modify->clearstep_compute(); + + for (m = 0; m < nvalues; m++) { + n = value2index[m]; + j = argindex[m]; + + // X,V,F adds coords,velocities,forces to values + + if (which[m] == X || which[m] == V || which[m] == F) { + double **attribute; + if (which[m] == X) attribute = x; + else if (which[m] == V) attribute = atom->v; + else attribute = atom->f; + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + values_one[layer[i]][m] += attribute[i][j]; + + // DENSITY_NUMBER adds 1 to values + + } else if (which[m] == DENSITY_NUMBER) { + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + values_one[layer[i]][m] += 1.0; + + // DENSITY_MASS adds mass to values + + } else if (which[m] == DENSITY_MASS) { + int *type = atom->type; + double *mass = atom->mass; + double *rmass = atom->rmass; + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + if (mass) values_one[layer[i]][m] += mass[type[i]]; + else values_one[layer[i]][m] += rmass[i]; + + // COMPUTE adds its scalar or vector component to values + // invoke compute if not previously invoked + + } else if (which[m] == COMPUTE) { + Compute *compute = modify->compute[n]; + if (!(compute->invoked & INVOKED_PERATOM)) compute->compute_peratom(); + double *scalar = compute->scalar_atom; + double **vector = compute->vector_atom; + int jm1 = j - 1; + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + if (j == 0) values_one[layer[i]][m] += scalar[i]; + else values_one[layer[i]][m] += vector[i][jm1]; + + // FIX adds its scalar or vector component to values + // access fix fields, guaranteed to be ready + + } else if (which[m] == FIX) { + double *scalar = modify->fix[n]->scalar_atom; + double **vector = modify->fix[n]->vector_atom; + int jm1 = j - 1; + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) { + if (j == 0) values_one[layer[i]][m] += scalar[i]; + else values_one[layer[i]][m] += vector[i][jm1]; + } + + // VARIABLE adds its per-atom quantities to values + // evaluate atom-style variable + + } else if (which[m] == VARIABLE) { + if (nlocal > maxatomvar) { + maxatomvar = atom->nmax; + memory->sfree(varatom); + varatom = (double *) + memory->smalloc(maxatomvar*sizeof(double),"ave/spatial:varatom"); + } + + input->variable->compute_atom(n,igroup,varatom,1,0); + + for (i = 0; i < nlocal; i++) + if (mask[i] & groupbit) + values_one[layer[i]][m] += varatom[i]; + } + } + + // process a single sample + // if normflag = ALL, accumulate values,count separately to many + // if normflag = SAMPLE, one = value/count, accumulate one to many + // exception is SAMPLE density: no normalization by atom count if (normflag == ALL) { for (m = 0; m < nlayers; m++) { @@ -560,8 +657,11 @@ void FixAveSpatial::end_of_step() MPI_Allreduce(count_one,count_many,nlayers,MPI_DOUBLE,MPI_SUM,world); for (m = 0; m < nlayers; m++) { if (count_many[m] > 0.0) - for (j = 0; j < nvalues; j++) - values_many[m][j] += values_one[m][j]/count_many[m]; + for (j = 0; j < nvalues; j++) { + if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS) + values_many[m][j] += values_one[m][j]; + else values_many[m][j] += values_one[m][j]/count_many[m]; + } count_sum[m] += count_many[m]; } } @@ -572,16 +672,18 @@ void FixAveSpatial::end_of_step() irepeat++; if (irepeat < nrepeat) { nvalid += nevery; - if (which == COMPUTE) modify->addstep_compute(nvalid); + modify->addstep_compute(nvalid); return; } irepeat = 0; nvalid = update->ntimestep+nfreq - (nrepeat-1)*nevery; - if (which == COMPUTE) modify->addstep_compute(nvalid); + modify->addstep_compute(nvalid); // time average across samples - // if density, also normalize by volume + // if normflag = ALL, final is total value / total count + // if normflag = SAMPLE, final is sum of ave / repeat + // exception is ALL density: normalized by repeat, not total count double repeat = nrepeat; @@ -592,7 +694,9 @@ void FixAveSpatial::end_of_step() for (m = 0; m < nlayers; m++) { if (count_sum[m] > 0.0) for (j = 0; j < nvalues; j++) - values_sum[m][j] /= count_sum[m]; + if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS) + values_sum[m][j] /= repeat; + else values_sum[m][j] /= count_sum[m]; count_sum[m] /= repeat; } } else { @@ -605,10 +709,12 @@ void FixAveSpatial::end_of_step() } } - if (which == DENSITY_MASS || which == DENSITY_NUM) { - for (m = 0; m < nlayers; m++) - values_sum[m][0] *= count_sum[m] / layer_volume; - } + // density is additionally normalized by layer volume + + for (j = 0; j < nvalues; j++) + if (which[j] == DENSITY_NUMBER || which[j] == DENSITY_MASS) + for (m = 0; m < nlayers; m++) + values_sum[m][j] /= layer_volume; // if ave = ONE, only single Nfreq timestep value is needed // if ave = RUNNING, combine with all previous Nfreq timestep values @@ -667,13 +773,24 @@ void FixAveSpatial::end_of_step() /* ---------------------------------------------------------------------- return Nth vector value since values_sum is 2d array, map N into ilayer and ivalue - if ilayer >= nlayers, just return 0, since nlayers can vary with time + if ilayer exceeds current layers, return 0.0 instead of generate an error ------------------------------------------------------------------------- */ double FixAveSpatial::compute_vector(int n) { int ivalue = n % nvalues; int ilayer = n / nvalues; - if (ilayer < nlayers && norm) return values_total[ilayer][ivalue]/norm; - return 0.0; + if (ilayer >= nlayers) return 0.0; + return values_total[ilayer][ivalue]/norm; +} + +/* ---------------------------------------------------------------------- + memory usage of varatom and layer +------------------------------------------------------------------------- */ + +double FixAveSpatial::memory_usage() +{ + double bytes = maxatomvar * sizeof(double); + bytes += maxatomlayer * sizeof(int); + return bytes; } diff --git a/src/fix_ave_spatial.h b/src/fix_ave_spatial.h index a9fabbe16e..fd2b089116 100644 --- a/src/fix_ave_spatial.h +++ b/src/fix_ave_spatial.h @@ -28,26 +28,31 @@ class FixAveSpatial : public Fix { void setup(); void end_of_step(); double compute_vector(int); + double memory_usage(); private: - int me; - int nrepeat,nfreq,irepeat,nvalid; - int dim,originflag,which,normflag; + int me,nvalues; + int nrepeat,nfreq,nvalid,irepeat; + int dim,originflag,normflag; double origin,delta; - char *id_compute,*id_fix; + int *which,*argindex,*value2index; + char **ids; FILE *fp; - int nlayers,nvalues,ave,nwindow; - int maxlayer,scaleflag,size_peratom; + int nlayers,ave,nwindow; + int maxlayer,scaleflag; double xscale,yscale,zscale; double layer_volume; double *coord; double *count_one,*count_many,*count_sum; double **values_one,**values_many,**values_sum; double offset,invdelta; - int ncompute; - class Compute **compute; - class Fix *fix; + + int maxatomvar; + double *varatom; + + int maxatomlayer; + int *layer; int norm,iwindow,window_limit; double *count_total; diff --git a/src/fix_ave_time.cpp b/src/fix_ave_time.cpp index 80d6c66f07..a0bc80df02 100644 --- a/src/fix_ave_time.cpp +++ b/src/fix_ave_time.cpp @@ -22,21 +22,25 @@ #include "modify.h" #include "compute.h" #include "group.h" +#include "input.h" +#include "variable.h" #include "memory.h" #include "error.h" using namespace LAMMPS_NS; -enum{COMPUTE,FIX}; -enum{SCALAR,VECTOR,BOTH}; +enum{COMPUTE,FIX,VARIABLE}; enum{ONE,RUNNING,WINDOW}; +#define INVOKED_SCALAR 1 // same as in computes +#define INVOKED_VECTOR 2 + /* ---------------------------------------------------------------------- */ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { - if (narg < 8) error->all("Illegal fix ave/time command"); + if (narg < 7) error->all("Illegal fix ave/time command"); MPI_Comm_rank(world,&me); @@ -44,37 +48,55 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) : nrepeat = atoi(arg[4]); nfreq = atoi(arg[5]); - if (strcmp(arg[6],"compute") == 0) which = COMPUTE; - else if (strcmp(arg[6],"fix") == 0) which = FIX; - else error->all("Illegal fix ave/time command"); + // parse values until one isn't recognized - int n = strlen(arg[7]) + 1; - id = new char[n]; - strcpy(id,arg[7]); + which = new int[narg-6]; + argindex = new int[narg-6]; + ids = new char*[narg-6]; + value2index = new int[narg-6]; + nvalues = 0; + + int iarg = 6; + while (iarg < narg) { + if ((strncmp(arg[iarg],"c_",2) == 0) || + (strncmp(arg[iarg],"f_",2) == 0) || + (strncmp(arg[iarg],"v_",2) == 0)) { + if (arg[iarg][0] == 'c') which[nvalues] = COMPUTE; + else if (arg[iarg][0] == 'f') which[nvalues] = FIX; + else if (arg[iarg][0] == 'v') which[nvalues] = VARIABLE; + + int n = strlen(arg[iarg]); + char *suffix = new char[n]; + strcpy(suffix,&arg[iarg][2]); + + char *ptr = strchr(suffix,'['); + if (ptr) { + if (suffix[strlen(suffix)-1] != ']') + error->all("Illegal fix ave/time command"); + argindex[nvalues] = atoi(ptr+1); + *ptr = '\0'; + } else argindex[nvalues] = 0; + + n = strlen(suffix) + 1; + ids[nvalues] = new char[n]; + strcpy(ids[nvalues],suffix); + nvalues++; + delete [] suffix; + + } else break; + + iarg++; + } // option defaults - sflag = 1; - vflag = 0; fp = NULL; ave = ONE; // optional args - int iarg = 8; while (iarg < narg) { - if (strcmp(arg[iarg],"type") == 0) { - if (iarg+2 > narg) error->all("Illegal fix ave/time command"); - if (strcmp(arg[iarg+1],"scalar") == 0) { - sflag = 1; - vflag = 0; - } else if (strcmp(arg[iarg+1],"vector") == 0) { - sflag = 0; - vflag = 1; - } else if (strcmp(arg[iarg+1],"both") == 0) sflag = vflag = 1; - else error->all("Illegal fix ave/time command"); - iarg += 2; - } else if (strcmp(arg[iarg],"file") == 0) { + if (strcmp(arg[iarg],"file") == 0) { if (iarg+2 > narg) error->all("Illegal fix ave/time command"); if (me == 0) { fp = fopen(arg[iarg+1],"w"); @@ -107,85 +129,108 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) : if (nfreq < nevery || nfreq % nevery || (nrepeat-1)*nevery >= nfreq) error->all("Illegal fix ave/time command"); - int icompute,ifix; - if (which == COMPUTE) { - icompute = modify->find_compute(id); - if (icompute < 0) error->all("Compute ID for fix ave/time does not exist"); - } else { - ifix = modify->find_fix(id); - if (ifix < 0) error->all("Fix ID for fix ave/time does not exist"); + for (int i = 0; i < nvalues; i++) { + if (which[i] == COMPUTE) { + int icompute = modify->find_compute(ids[i]); + if (icompute < 0) + error->all("Compute ID for fix ave/time does not exist"); + if (argindex[i] == 0 && modify->compute[icompute]->scalar_flag == 0) + error->all("Fix ave/time compute does not calculate a scalar"); + if (argindex[i] && modify->compute[icompute]->vector_flag == 0) + error->all("Fix ave/time compute does not calculate a vector"); + if (argindex[i] && argindex[i] > modify->compute[icompute]->size_vector) + error->all("Fix ave/time compute vector is accessed out-of-range"); + } else if (which[i] == FIX) { + int ifix = modify->find_fix(ids[i]); + if (ifix < 0) + error->all("Fix ID for fix ave/time does not exist"); + if (argindex[i] && modify->fix[ifix]->scalar_flag == 0) + error->all("Fix ave/time fix does not calculate a scalar"); + if (argindex[i] && modify->fix[ifix]->vector_flag == 0) + error->all("Fix ave/time fix does not calculate a vector"); + if (argindex[i] && argindex[i] > modify->fix[ifix]->size_vector) + error->all("Fix ave/time fix vector is accessed out-of-range"); + } else if (which[i] == VARIABLE) { + int ivariable = input->variable->find(ids[i]); + if (ivariable < 0) + error->all("Variable name for fix ave/time does not exist"); + if (input->variable->equalstyle(ivariable) == 0) + error->all("Fix ave/time variable is not equal-style variable"); + } } - if (which == COMPUTE) { - if (sflag && modify->compute[icompute]->scalar_flag == 0) - error->all("Fix ave/time compute does not calculate a scalar"); - if (vflag && modify->compute[icompute]->vector_flag == 0) - error->all("Fix ave/time compute does not calculate a vector"); - } else { - if (sflag && modify->fix[ifix]->scalar_flag == 0) - error->all("Fix ave/time fix does not calculate a scalar"); - if (vflag && modify->fix[ifix]->vector_flag == 0) - error->all("Fix ave/time fix does not calculate a vector"); - } - - // setup list of computes to call, including pre-computes - - compute = NULL; - if (which == COMPUTE) { - ncompute = 1 + modify->compute[icompute]->npre; - compute = new Compute*[ncompute]; - } else ncompute = 0; - // print header into file if (fp && me == 0) { - if (which == COMPUTE) - fprintf(fp,"Time-averaged data for fix %s, group %s, and compute %s\n", - id,group->names[modify->compute[icompute]->igroup],id); - else - fprintf(fp,"Time-averaged data for fix %s, group %s, and fix %s\n", - id,group->names[modify->fix[ifix]->igroup],id); - if (sflag and !vflag) - fprintf(fp,"TimeStep Value\n"); - else if (!sflag and vflag) - fprintf(fp,"TimeStep Vector-values\n"); - else if (!sflag and vflag) - fprintf(fp,"TimeStep Scalar-value Vector-values\n"); + fprintf(fp,"Time-averaged data for fix %s\n",id); + fprintf(fp,"TimeStep"); + for (int i = 0; i < nvalues; i++) + if (which[i] == COMPUTE) fprintf(fp," c_%s",ids[i]); + else if (which[i] == FIX) fprintf(fp," f_%s",ids[i]); + else if (which[i] == VARIABLE) fprintf(fp," v_%s",ids[i]); + fprintf(fp,"\n"); } - // allocate memory for averaging + // allocate and initialize memory for averaging - vector = vector_total = NULL; - if (vflag) { - if (which == COMPUTE) size_vector = modify->compute[icompute]->size_vector; - else size_vector = modify->fix[ifix]->size_vector; - vector = new double[size_vector]; - vector_total = new double[size_vector]; - } + vector = new double[nvalues]; + vector_total = new double[nvalues]; + for (int i = 0; i < nvalues; i++) vector_total[i] = 0.0; - scalar_list = NULL; vector_list = NULL; - if (sflag && ave == WINDOW) scalar_list = new double[nwindow]; - if (vflag && ave == WINDOW) - vector_list = memory->create_2d_double_array(nwindow,size_vector, + if (ave == WINDOW) + vector_list = memory->create_2d_double_array(nwindow,nvalues, "ave/time:vector_list"); - // enable this fix to produce a global scalar and/or vector + // this fix produces either a global scalar or vector + // intensive/extensive flags set by compute,fix,variable that produces value - if (sflag) scalar_flag = 1; - if (vflag) vector_flag = 1; scalar_vector_freq = nfreq; - if (which == COMPUTE) extensive = modify->compute[icompute]->extensive; - else extensive = modify->fix[ifix]->extensive; + extlist = NULL; + + if (nvalues == 1) { + scalar_flag = 1; + if (which[0] == COMPUTE) { + Compute *compute = modify->compute[modify->find_compute(ids[0])]; + if (argindex[0] == 0) extscalar = compute->extscalar; + else if (compute->extvector >= 0) extscalar = compute->extvector; + else extscalar = compute->extlist[argindex[0]-1]; + } else if (which[0] == FIX) { + Fix *fix = modify->fix[modify->find_fix(ids[0])]; + if (argindex[0] == 0) extscalar = fix->extscalar; + else if (fix->extvector >= 0) extscalar = fix->extvector; + else extscalar = fix->extlist[argindex[0]-1]; + } else if (which[0] == VARIABLE) + extscalar = 0; + + } else { + vector_flag = 1; + size_vector = nvalues; + extvector = -1; + extlist = new int[nvalues]; + for (int i = 0; i < nvalues; i++) { + if (which[i] == COMPUTE) { + Compute *compute = modify->compute[modify->find_compute(ids[i])]; + if (argindex[i] == 0) extlist[i] = compute->extscalar; + else if (compute->extvector >= 0) extlist[i] = compute->extvector; + else extlist[i] = compute->extlist[argindex[i]-1]; + } else if (which[i] == FIX) { + Fix *fix = modify->fix[modify->find_fix(ids[i])]; + if (argindex[i] == 0) extlist[i] = fix->extscalar; + else if (fix->extvector >= 0) extlist[i] = fix->extvector; + else extlist[i] = fix->extlist[argindex[i]-1]; + } else if (which[i] == VARIABLE) + extlist[i] = 0; + } + } // initializations - // set scalar and vector total to zero since they accumulate + // set vector total to zero since it accumulates irepeat = 0; iwindow = window_limit = 0; norm = 0; - scalar_total = 0.0; - if (vflag) for (int i = 0; i < size_vector; i++) vector_total[i] = 0.0; + for (int i = 0; i < nvalues; i++) vector_total[i] = 0.0; // nvalid = next step on which end_of_step does something // can be this timestep if multiple of nfreq and nrepeat = 1 @@ -198,24 +243,27 @@ FixAveTime::FixAveTime(LAMMPS *lmp, int narg, char **arg) : nvalid -= (nrepeat-1)*nevery; if (nvalid < update->ntimestep) nvalid += nfreq; - // set timestep for all computes that store invocation times - // since don't know a priori which are invoked by this fix + // add nvalid to ALL computes that store invocation times + // since don't know a priori which are invoked by this fix // once in end_of_step() can just set timestep for ones actually invoked - for (int i = 0; i < modify->ncompute; i++) - if (modify->compute[i]->timeflag) modify->compute[i]->add_step(nvalid); + modify->addstep_compute_all(nvalid); } /* ---------------------------------------------------------------------- */ FixAveTime::~FixAveTime() { - delete [] id; + delete [] which; + delete [] argindex; + for (int i = 0; i < nvalues; i++) delete [] ids[i]; + delete [] ids; + delete [] value2index; + delete [] extlist; + if (fp && me == 0) fclose(fp); - delete [] compute; delete [] vector; delete [] vector_total; - delete [] scalar_list; memory->destroy_2d_double_array(vector_list); } @@ -232,36 +280,33 @@ int FixAveTime::setmask() void FixAveTime::init() { - // set ptrs to compute and its pre-computes called each end-of-step - // put pre-computes in list before compute - - if (which == COMPUTE) { - int icompute = modify->find_compute(id); - if (icompute < 0) - error->all("Compute ID for fix ave/time does not exist"); - - ncompute = 0; - if (modify->compute[icompute]->npre) - for (int i = 0; i < modify->compute[icompute]->npre; i++) { - int ic = modify->find_compute(modify->compute[icompute]->id_pre[i]); - if (ic < 0) - error->all("Precompute ID for fix ave/time does not exist"); - compute[ncompute++] = modify->compute[ic]; - } - - compute[ncompute++] = modify->compute[icompute]; - } - - // set ptr to fix ID + // set indices and check validity of all computes,fixes,variables // check that fix frequency is acceptable - if (which == FIX) { - int ifix = modify->find_fix(id); - if (ifix < 0) - error->all("Fix ID for fix ave/time does not exist"); - fix = modify->fix[ifix]; - if (nevery % fix->scalar_vector_freq) - error->all("Fix ave/time and fix not computed at compatible times"); + int ilist = 0; + + for (int i = 0; i < nvalues; i++) { + if (which[i] == COMPUTE) { + int icompute = modify->find_compute(ids[i]); + if (icompute < 0) + error->all("Compute ID for fix ave/time does not exist"); + value2index[i] = icompute; + + } else if (which[i] == FIX) { + int ifix = modify->find_fix(ids[i]); + if (ifix < 0) + error->all("Fix ID for fix ave/time does not exist"); + value2index[i] = ifix; + + if (nevery % modify->fix[ifix]->scalar_vector_freq) + error->all("Fix for fix ave/time not computed at compatible time"); + + } else if (which[i] == VARIABLE) { + int ivariable = input->variable->find(ids[i]); + if (ivariable < 0) + error->all("Variable name for fix ave/time does not exist"); + value2index[i] = ivariable; + } } } @@ -278,7 +323,8 @@ void FixAveTime::setup() void FixAveTime::end_of_step() { - int i; + int i,j,k,m; + double tmp; // skip if not step which requires doing something @@ -286,33 +332,44 @@ void FixAveTime::end_of_step() // zero if first step - if (irepeat == 0) { - scalar = 0.0; - if (vflag) - for (i = 0; i < size_vector; i++) vector[i] = 0.0; - } + if (irepeat == 0) + for (i = 0; i < nvalues; i++) vector[i] = 0.0; - // accumulate results of compute or fix to local copy - - if (which == COMPUTE) { - modify->clearstep_compute(); + // accumulate results of computes,fixes,variables to local copy + // compute/fix/variable may invoke computes so wrap with clear/add - if (sflag) { - double value; - for (i = 0; i < ncompute; i++) value = compute[i]->compute_scalar(); - scalar += value; - } - if (vflag) { - for (i = 0; i < ncompute; i++) compute[i]->compute_vector(); - double *cvector = compute[ncompute-1]->vector; - for (i = 0; i < size_vector; i++) vector[i] += cvector[i]; - } + modify->clearstep_compute(); - } else { - if (sflag) scalar += fix->compute_scalar(); - if (vflag) - for (i = 0; i < size_vector; i++) - vector[i] += fix->compute_vector(i); + int ilist = 0; + + for (i = 0; i < nvalues; i++) { + m = value2index[i]; + + // invoke compute if not previously invoked + + if (which[i] == COMPUTE) { + Compute *compute = modify->compute[m]; + + if (argindex[i] == 0) { + if (compute->invoked & INVOKED_SCALAR) vector[i] += compute->scalar; + else vector[i] += compute->compute_scalar(); + } else { + if (!(compute->invoked & INVOKED_VECTOR)) compute->compute_vector(); + vector[i] += compute->vector[argindex[i]-1]; + } + + // access fix fields, guaranteed to be ready + + } else if (which[i] == FIX) { + if (argindex[i] == 0) + vector[i] += modify->fix[m]->compute_scalar(); + else + vector[i] += modify->fix[m]->compute_vector(argindex[i]-1); + + // evaluate equal-style variable + + } else if (which[i] == VARIABLE) + vector[i] += input->variable->compute_equal(m); } // done if irepeat < nrepeat @@ -321,46 +378,36 @@ void FixAveTime::end_of_step() irepeat++; if (irepeat < nrepeat) { nvalid += nevery; - if (which == COMPUTE) modify->addstep_compute(nvalid); + modify->addstep_compute(nvalid); return; } irepeat = 0; nvalid = update->ntimestep+nfreq - (nrepeat-1)*nevery; - if (which == COMPUTE) modify->addstep_compute(nvalid); + modify->addstep_compute(nvalid); // average the final result for the Nfreq timestep double repeat = nrepeat; - if (sflag) scalar /= repeat; - if (vflag) for (i = 0; i < size_vector; i++) vector[i] /= repeat; + for (i = 0; i < nvalues; i++) vector[i] /= repeat; // if ave = ONE, only single Nfreq timestep value is needed // if ave = RUNNING, combine with all previous Nfreq timestep values // if ave = WINDOW, comine with nwindow most recent Nfreq timestep values if (ave == ONE) { - if (sflag) scalar_total = scalar; - if (vflag) for (i = 0; i < size_vector; i++) vector_total[i] = vector[i]; + for (i = 0; i < nvalues; i++) vector_total[i] = vector[i]; norm = 1; } else if (ave == RUNNING) { - if (sflag) scalar_total += scalar; - if (vflag) for (i = 0; i < size_vector; i++) vector_total[i] += vector[i]; + for (i = 0; i < nvalues; i++) vector_total[i] += vector[i]; norm++; } else if (ave == WINDOW) { - if (sflag) { - scalar_total += scalar; - if (window_limit) scalar_total -= scalar_list[iwindow]; - scalar_list[iwindow] = scalar; - } - if (vflag) { - for (i = 0; i < size_vector; i++) { - vector_total[i] += vector[i]; - if (window_limit) vector_total[i] -= vector_list[iwindow][i]; - vector_list[iwindow][i] = vector[i]; - } + for (i = 0; i < nvalues; i++) { + vector_total[i] += vector[i]; + if (window_limit) vector_total[i] -= vector_list[iwindow][i]; + vector_list[iwindow][i] = vector[i]; } iwindow++; @@ -376,9 +423,7 @@ void FixAveTime::end_of_step() if (fp && me == 0) { fprintf(fp,"%d",update->ntimestep); - if (sflag) fprintf(fp," %g",scalar_total/norm); - if (vflag) - for (i = 0; i < size_vector; i++) fprintf(fp," %g",vector_total[i]/norm); + for (i = 0; i < nvalues; i++) fprintf(fp," %g",vector_total[i]/norm); fprintf(fp,"\n"); fflush(fp); } @@ -391,7 +436,7 @@ void FixAveTime::end_of_step() double FixAveTime::compute_scalar() { - if (norm) return scalar_total/norm; + if (norm) return vector_total[0]/norm; return 0.0; } diff --git a/src/fix_ave_time.h b/src/fix_ave_time.h index 22f3fecbc3..ea0103e9ea 100644 --- a/src/fix_ave_time.h +++ b/src/fix_ave_time.h @@ -31,20 +31,16 @@ class FixAveTime : public Fix { double compute_vector(int); private: - int me; - int nrepeat,nfreq,nvalid,irepeat,which,ifix; - char *id; + int me,nvalues; + int nrepeat,nfreq,nvalid,irepeat; + int *which,*argindex,*value2index; + char **ids; FILE *fp; - int sflag,vflag,ave,nwindow,nsum; - double scalar,*vector; - int ncompute; - class Compute **compute; - class Fix *fix; + int ave,nwindow,nsum; + double *vector; int norm,iwindow,window_limit; - double scalar_total; - double *scalar_list; double *vector_total; double **vector_list; }; diff --git a/src/fix_drag.cpp b/src/fix_drag.cpp index 7ef928c72e..72fdf9c8db 100644 --- a/src/fix_drag.cpp +++ b/src/fix_drag.cpp @@ -33,7 +33,7 @@ FixDrag::FixDrag(LAMMPS *lmp, int narg, char **arg) : vector_flag = 1; size_vector = 3; scalar_vector_freq = 1; - extensive = 1; + extvector = 1; xflag = yflag = zflag = 1; @@ -46,6 +46,9 @@ FixDrag::FixDrag(LAMMPS *lmp, int narg, char **arg) : f_mag = atof(arg[6]); delta = atof(arg[7]); + + force_flag = 0; + ftotal[0] = ftotal[1] = ftotal[2] = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_dt_reset.cpp b/src/fix_dt_reset.cpp index 44152f9505..bab0d0e6b7 100644 --- a/src/fix_dt_reset.cpp +++ b/src/fix_dt_reset.cpp @@ -47,7 +47,8 @@ FixDtReset::FixDtReset(LAMMPS *lmp, int narg, char **arg) : vector_flag = 1; size_vector = 1; scalar_vector_freq = 1; - extensive = 0; + extscalar = 0; + extvector = 0; nevery = atoi(arg[3]); if (nevery <= 0) error->all("Illegal fix dt/reset command"); diff --git a/src/fix_indent.cpp b/src/fix_indent.cpp index b4aec7d59a..9c697e7546 100644 --- a/src/fix_indent.cpp +++ b/src/fix_indent.cpp @@ -42,7 +42,8 @@ FixIndent::FixIndent(LAMMPS *lmp, int narg, char **arg) : vector_flag = 1; size_vector = 3; scalar_vector_freq = 1; - extensive = 1; + extscalar = 1; + extvector = 1; k = atof(arg[3]); @@ -103,6 +104,9 @@ FixIndent::FixIndent(LAMMPS *lmp, int narg, char **arg) : r0_start *= zscale; } } else error->all("Illegal fix indent command"); + + indenter_flag = 0; + indenter[0] = indenter[1] = indenter[2] = indenter[3] = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_nph.cpp b/src/fix_nph.cpp index ae5d629b03..62dfe86138 100644 --- a/src/fix_nph.cpp +++ b/src/fix_nph.cpp @@ -48,7 +48,7 @@ FixNPH::FixNPH(LAMMPS *lmp, int narg, char **arg) : box_change = 1; scalar_flag = 1; scalar_vector_freq = 1; - extensive = 1; + extscalar = 1; double p_period[3]; if (strcmp(arg[3],"xyz") == 0) { @@ -242,7 +242,6 @@ void FixNPH::init() } // set temperature and pressure ptrs - // set ptemperature only if pressure's id_pre[0] is not id_temp int icompute = modify->find_compute(id_temp); if (icompute < 0) error->all("Temp ID for fix nph does not exist"); @@ -252,14 +251,6 @@ void FixNPH::init() if (icompute < 0) error->all("Press ID for fix nph does not exist"); pressure = modify->compute[icompute]; - if (strcmp(id_temp,pressure->id_pre[0]) == 0) ptemperature = NULL; - else { - icompute = modify->find_compute(pressure->id_pre[0]); - if (icompute < 0) - error->all("Temp ID of press ID for fix nph does not exist"); - ptemperature = modify->compute[icompute]; - } - // set timesteps and frequencies // Nkt = initial value for piston mass and energy conservation // guesstimate a unit-dependent t_initial if actual T = 0.0 @@ -323,18 +314,16 @@ void FixNPH::setup() double tmp = temperature->compute_scalar(); if (press_couple == 0) { - if (ptemperature) tmp = ptemperature->compute_scalar(); tmp = pressure->compute_scalar(); } else { temperature->compute_vector(); - if (ptemperature) ptemperature->compute_vector(); pressure->compute_vector(); } couple(); // trigger virial computation on next timestep - pressure->add_step(update->ntimestep+1); + pressure->addstep(update->ntimestep+1); } /* ---------------------------------------------------------------------- @@ -438,18 +427,16 @@ void FixNPH::final_integrate() double tmp = temperature->compute_scalar(); if (press_couple == 0) { - if (ptemperature) tmp = ptemperature->compute_scalar(); tmp = pressure->compute_scalar(); } else { temperature->compute_vector(); - if (ptemperature) ptemperature->compute_vector(); pressure->compute_vector(); } couple(); // trigger virial computation on next timestep - pressure->add_step(update->ntimestep+1); + pressure->addstep(update->ntimestep+1); // update omega_dot // for non-varying dims, p_freq is 0.0, so omega_dot doesn't change @@ -752,13 +739,13 @@ int FixNPH::modify_param(int narg, char **arg) if (temperature->igroup != 0 && comm->me == 0) error->warning("Temperature for NPH is not for group all"); - // reset id_pre[0] of pressure to new temp ID + // reset id_pre of pressure to new temp ID icompute = modify->find_compute(id_press); if (icompute < 0) error->all("Press ID for fix npt does not exist"); - delete [] modify->compute[icompute]->id_pre[0]; - modify->compute[icompute]->id_pre[0] = new char[n]; - strcpy(modify->compute[icompute]->id_pre[0],id_temp); + delete [] modify->compute[icompute]->id_pre; + modify->compute[icompute]->id_pre = new char[n]; + strcpy(modify->compute[icompute]->id_pre,id_temp); return 2; diff --git a/src/fix_nph.h b/src/fix_nph.h index 09ec8d540d..fe003a2d88 100644 --- a/src/fix_nph.h +++ b/src/fix_nph.h @@ -56,7 +56,7 @@ class FixNPH : public Fix { double *step_respa; char *id_temp,*id_press; - class Compute *temperature,*pressure,*ptemperature; + class Compute *temperature,*pressure; int tflag,pflag; void couple(); diff --git a/src/fix_npt.cpp b/src/fix_npt.cpp index a29692229e..820ad96e36 100644 --- a/src/fix_npt.cpp +++ b/src/fix_npt.cpp @@ -47,7 +47,7 @@ FixNPT::FixNPT(LAMMPS *lmp, int narg, char **arg) : box_change = 1; scalar_flag = 1; scalar_vector_freq = 1; - extensive = 1; + extscalar = 1; t_start = atof(arg[3]); t_stop = atof(arg[4]); @@ -252,7 +252,6 @@ void FixNPT::init() } // set temperature and pressure ptrs - // set ptemperature only if pressure's id_pre[0] is not id_temp int icompute = modify->find_compute(id_temp); if (icompute < 0) error->all("Temp ID for fix npt does not exist"); @@ -262,14 +261,6 @@ void FixNPT::init() if (icompute < 0) error->all("Press ID for fix npt does not exist"); pressure = modify->compute[icompute]; - if (strcmp(id_temp,pressure->id_pre[0]) == 0) ptemperature = NULL; - else { - icompute = modify->find_compute(pressure->id_pre[0]); - if (icompute < 0) - error->all("Temp ID of press ID for fix npt does not exist"); - ptemperature = modify->compute[icompute]; - } - // set timesteps and frequencies dtv = update->dt; @@ -325,18 +316,16 @@ void FixNPT::setup() t_current = temperature->compute_scalar(); if (press_couple == 0) { - if (ptemperature) double ptmp = ptemperature->compute_scalar(); double tmp = pressure->compute_scalar(); } else { temperature->compute_vector(); - if (ptemperature) ptemperature->compute_vector(); pressure->compute_vector(); } couple(); // trigger virial computation on next timestep - pressure->add_step(update->ntimestep+1); + pressure->addstep(update->ntimestep+1); } /* ---------------------------------------------------------------------- @@ -448,18 +437,16 @@ void FixNPT::final_integrate() t_current = temperature->compute_scalar(); if (press_couple == 0) { - if (ptemperature) double ptmp = ptemperature->compute_scalar(); double tmp = pressure->compute_scalar(); } else { temperature->compute_vector(); - if (ptemperature) ptemperature->compute_vector(); pressure->compute_vector(); } couple(); // trigger virial computation on next timestep - pressure->add_step(update->ntimestep+1); + pressure->addstep(update->ntimestep+1); // update eta_dot @@ -781,13 +768,13 @@ int FixNPT::modify_param(int narg, char **arg) if (temperature->igroup != 0 && comm->me == 0) error->warning("Temperature for NPT is not for group all"); - // reset id_pre[0] of pressure to new temp ID + // reset id_pre of pressure to new temp ID icompute = modify->find_compute(id_press); if (icompute < 0) error->all("Press ID for fix npt does not exist"); - delete [] modify->compute[icompute]->id_pre[0]; - modify->compute[icompute]->id_pre[0] = new char[n]; - strcpy(modify->compute[icompute]->id_pre[0],id_temp); + delete [] modify->compute[icompute]->id_pre; + modify->compute[icompute]->id_pre = new char[n]; + strcpy(modify->compute[icompute]->id_pre,id_temp); return 2; diff --git a/src/fix_npt.h b/src/fix_npt.h index 25703778d9..9505e7513e 100644 --- a/src/fix_npt.h +++ b/src/fix_npt.h @@ -62,7 +62,7 @@ class FixNPT : public Fix { double *step_respa; char *id_temp,*id_press; - class Compute *temperature,*pressure,*ptemperature; + class Compute *temperature,*pressure; int tflag,pflag; void couple(); diff --git a/src/fix_nvt.cpp b/src/fix_nvt.cpp index 371c208bf8..cb194e3de1 100644 --- a/src/fix_nvt.cpp +++ b/src/fix_nvt.cpp @@ -41,7 +41,7 @@ FixNVT::FixNVT(LAMMPS *lmp, int narg, char **arg) : restart_global = 1; scalar_flag = 1; scalar_vector_freq = 1; - extensive = 1; + extscalar = 1; t_start = atof(arg[3]); t_stop = atof(arg[4]); diff --git a/src/fix_orient_fcc.cpp b/src/fix_orient_fcc.cpp index 8f97bc6181..7599140b5c 100644 --- a/src/fix_orient_fcc.cpp +++ b/src/fix_orient_fcc.cpp @@ -48,7 +48,7 @@ FixOrientFCC::FixOrientFCC(LAMMPS *lmp, int narg, char **arg) : scalar_flag = 1; scalar_vector_freq = 1; - extensive = 1; + extscalar = 1; nstats = atoi(arg[3]); direction_of_motion = atoi(arg[4]); @@ -149,6 +149,8 @@ FixOrientFCC::FixOrientFCC(LAMMPS *lmp, int narg, char **arg) : if (use_xismooth) comm_forward = 62; else comm_forward = 50; + + added_energy = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_print.cpp b/src/fix_print.cpp index e4d8d7dbe4..1ac89724ba 100644 --- a/src/fix_print.cpp +++ b/src/fix_print.cpp @@ -101,7 +101,7 @@ void FixPrint::end_of_step() // make a copy of string to work on // substitute for $ variables (no printing) // append a newline and print final copy - // variable evaluation may invoke a compute that affects Verlet::eflag,vflag + // variable evaluation may invoke computes so wrap with clear/add modify->clearstep_compute(); diff --git a/src/fix_set_force.cpp b/src/fix_set_force.cpp index d3eda26fcc..795723959c 100644 --- a/src/fix_set_force.cpp +++ b/src/fix_set_force.cpp @@ -31,7 +31,7 @@ FixSetForce::FixSetForce(LAMMPS *lmp, int narg, char **arg) : vector_flag = 1; size_vector = 3; scalar_vector_freq = 1; - extensive = 1; + extvector = 1; flagx = flagy = flagz = 1; if (strcmp(arg[3],"NULL") == 0) flagx = 0; @@ -40,6 +40,9 @@ FixSetForce::FixSetForce(LAMMPS *lmp, int narg, char **arg) : else yvalue = atof(arg[4]); if (strcmp(arg[5],"NULL") == 0) flagz = 0; else zvalue = atof(arg[5]); + + force_flag = 0; + foriginal[0] = foriginal[1] = foriginal[2] = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_spring.cpp b/src/fix_spring.cpp index a38c64ff86..771f8f81c3 100644 --- a/src/fix_spring.cpp +++ b/src/fix_spring.cpp @@ -41,7 +41,7 @@ FixSpring::FixSpring(LAMMPS *lmp, int narg, char **arg) : vector_flag = 1; size_vector = 3; scalar_vector_freq = 1; - extensive = 1; + extvector = 1; if (strcmp(arg[3],"tether") == 0) { if (narg != 9) error->all("Illegal fix spring command"); @@ -78,6 +78,9 @@ FixSpring::FixSpring(LAMMPS *lmp, int narg, char **arg) : if (r0 < 0) error->all("R0 < 0 for fix spring command"); } else error->all("Illegal fix spring command"); + + force_flag = 0; + ftotal[0] = ftotal[1] = ftotal[2] = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_temp_rescale.cpp b/src/fix_temp_rescale.cpp index 827ecdf660..1b352e7086 100644 --- a/src/fix_temp_rescale.cpp +++ b/src/fix_temp_rescale.cpp @@ -42,7 +42,7 @@ FixTempRescale::FixTempRescale(LAMMPS *lmp, int narg, char **arg) : scalar_flag = 1; scalar_vector_freq = nevery; - extensive = 1; + extscalar = 1; t_start = atof(arg[4]); t_end = atof(arg[5]); @@ -109,6 +109,8 @@ FixTempRescale::FixTempRescale(LAMMPS *lmp, int narg, char **arg) : } delete [] newarg; tflag = 1; + + energy = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_viscosity.cpp b/src/fix_viscosity.cpp index 1af6bdedd1..3ed08614c0 100644 --- a/src/fix_viscosity.cpp +++ b/src/fix_viscosity.cpp @@ -39,7 +39,7 @@ FixViscosity::FixViscosity(LAMMPS *lmp, int narg, char **arg) : scalar_flag = 1; scalar_vector_freq = nevery; - extensive = 0; + extscalar = 0; if (strcmp(arg[4],"x") == 0) vdim = 0; else if (strcmp(arg[4],"y") == 0) vdim = 1; diff --git a/src/fix_wall_lj126.cpp b/src/fix_wall_lj126.cpp index 891882d4fd..e7fa0af8fc 100644 --- a/src/fix_wall_lj126.cpp +++ b/src/fix_wall_lj126.cpp @@ -39,7 +39,8 @@ FixWallLJ126::FixWallLJ126(LAMMPS *lmp, int narg, char **arg) : vector_flag = 1; size_vector = 3; scalar_vector_freq = 1; - extensive = 1; + extscalar = 1; + extvector = 1; if (strcmp(arg[3],"xlo") == 0) { dim = 0; @@ -81,6 +82,9 @@ FixWallLJ126::FixWallLJ126(LAMMPS *lmp, int narg, char **arg) : error->all("Cannot use wall in periodic dimension"); if (dim == 2 && domain->zperiodic) error->all("Cannot use wall in periodic dimension"); + + wall_flag = 0; + wall[0] = wall[1] = wall[2] = wall[3] = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/fix_wall_lj93.cpp b/src/fix_wall_lj93.cpp index a9335792bd..4c433d7f91 100644 --- a/src/fix_wall_lj93.cpp +++ b/src/fix_wall_lj93.cpp @@ -35,7 +35,8 @@ FixWallLJ93::FixWallLJ93(LAMMPS *lmp, int narg, char **arg) : vector_flag = 1; size_vector = 3; scalar_vector_freq = 1; - extensive = 1; + extscalar = 1; + extvector = 1; if (strcmp(arg[3],"xlo") == 0) { dim = 0; @@ -78,6 +79,9 @@ FixWallLJ93::FixWallLJ93(LAMMPS *lmp, int narg, char **arg) : error->all("Cannot use wall in periodic dimension"); if (dim == 2 && domain->zperiodic) error->all("Cannot use wall in periodic dimension"); + + wall_flag = 0; + wall[0] = wall[1] = wall[2] = wall[3] = 0.0; } /* ---------------------------------------------------------------------- */ diff --git a/src/input.cpp b/src/input.cpp index 886564fb95..191fe39c02 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -262,7 +262,7 @@ char *Input::one(const char *single) command = first word narg = # of args arg[] = individual args - treat multiple args between double quotes as one arg + treat text between double quotes as one arg ------------------------------------------------------------------------- */ void Input::parse() @@ -311,10 +311,13 @@ void Input::parse() arg[narg] = strtok(NULL," \t\n\r\f"); if (arg[narg] && arg[narg][0] == '\"') { arg[narg] = &arg[narg][1]; - if (strchr(arg[narg],'\"')) error->all("Quotes in a single arg"); - arg[narg][strlen(arg[narg])] = ' '; - ptr = strtok(NULL,"\""); - if (ptr == NULL) error->all("Unbalanced quotes in input line"); + if (arg[narg][strlen(arg[narg])-1] == '\"') + arg[narg][strlen(arg[narg])-1] = '\0'; + else { + arg[narg][strlen(arg[narg])] = ' '; + ptr = strtok(arg[narg],"\""); + if (ptr == NULL) error->all("Unbalanced quotes in input line"); + } } if (arg[narg]) narg++; else break; @@ -355,7 +358,7 @@ void Input::substitute(char *str, int flag) beyond = ptr + strlen(var) + 1; } value = variable->retrieve(var); - if (value == NULL) error->one("Substitution for undefined variable"); + if (value == NULL) error->one("Substitution for illegal variable"); *ptr = '\0'; strcpy(work,str); diff --git a/src/integrate.cpp b/src/integrate.cpp index e2b62c0e84..1225a56a8b 100644 --- a/src/integrate.cpp +++ b/src/integrate.cpp @@ -96,24 +96,24 @@ void Integrate::ev_set(int ntimestep) int eflag_global = 0; for (i = 0; i < nelist_global; i++) - if (elist_global[i]->match_step(ntimestep)) break; + if (elist_global[i]->matchstep(ntimestep)) break; if (i < nelist_global) eflag_global = 1; int eflag_atom = 0; for (i = 0; i < nelist_atom; i++) - if (elist_atom[i]->match_step(ntimestep)) break; + if (elist_atom[i]->matchstep(ntimestep)) break; if (i < nelist_atom) eflag_atom = 2; eflag = eflag_global + eflag_atom; int vflag_global = 0; for (i = 0; i < nvlist_global; i++) - if (vlist_global[i]->match_step(ntimestep)) break; + if (vlist_global[i]->matchstep(ntimestep)) break; if (i < nvlist_global) vflag_global = virial_style; int vflag_atom = 0; for (i = 0; i < nvlist_atom; i++) - if (vlist_atom[i]->match_step(ntimestep)) break; + if (vlist_atom[i]->matchstep(ntimestep)) break; if (i < nvlist_atom) vflag_atom = 4; vflag = vflag_global + vflag_atom; diff --git a/src/min.cpp b/src/min.cpp index 017d82bc7b..08e406429a 100644 --- a/src/min.cpp +++ b/src/min.cpp @@ -133,19 +133,19 @@ void Min::ev_set(int ntimestep) int eflag_atom = 0; for (i = 0; i < nelist_atom; i++) - if (elist_atom[i]->match_step(ntimestep)) break; + if (elist_atom[i]->matchstep(ntimestep)) break; if (i < nelist_atom) eflag_atom = 2; eflag = eflag_global + eflag_atom; int vflag_global = 0; for (i = 0; i < nvlist_global; i++) - if (vlist_global[i]->match_step(ntimestep)) break; + if (vlist_global[i]->matchstep(ntimestep)) break; if (i < nvlist_global) vflag_global = virial_style; int vflag_atom = 0; for (i = 0; i < nvlist_atom; i++) - if (vlist_atom[i]->match_step(ntimestep)) break; + if (vlist_atom[i]->matchstep(ntimestep)) break; if (i < nvlist_atom) vflag_atom = 4; vflag = vflag_global + vflag_atom; diff --git a/src/min_cg.cpp b/src/min_cg.cpp index d65ce47b92..72bafad0b4 100644 --- a/src/min_cg.cpp +++ b/src/min_cg.cpp @@ -164,10 +164,10 @@ void MinCG::run() // account for early exit from iterate loop due to convergence // set niter/nsteps for Finish stats to print // set output->next values to this timestep - // set timestep for all computes that store invocation times - // since don't know a priori which are invoked by thermo and dumps // call eng_force to insure vflag is set when forces computed // output->write does final output for thermo, dump, restart files + // add ntimestep to ALL computes that store invocation times + // since just hardwired call to thermo/dumps and they may not be ready if (niter < update->nsteps) { niter++; @@ -179,9 +179,7 @@ void MinCG::run() if (output->restart_every) output->next_restart = update->ntimestep; output->next_thermo = update->ntimestep; - for (int i = 0; i < modify->ncompute; i++) - if (modify->compute[i]->timeflag) - modify->compute[i]->add_step(update->ntimestep); + modify->addstep_compute_all(update->ntimestep); int ntmp; double *xtmp,*htmp,etmp; diff --git a/src/modify.cpp b/src/modify.cpp index eaf82d90a1..f0fc74069b 100644 --- a/src/modify.cpp +++ b/src/modify.cpp @@ -132,11 +132,6 @@ void Modify::init() restart_deallocate(); - // init each fix - - comm->maxforward_fix = comm->maxreverse_fix = 0; - for (i = 0; i < nfix; i++) fix[i]->init(); - // create lists of fixes to call at each stage of run list_init(INITIAL_INTEGRATE,n_initial_integrate,list_initial_integrate); @@ -161,13 +156,16 @@ void Modify::init() list_init_compute(); - // init each compute - // for computes that store invocation times, add initial step to their list + // init each fix, must come after call to list_init_compute() - for (i = 0; i < ncompute; i++) { - compute[i]->init(); - if (compute[i]->timeflag) compute[i]->add_step(update->ntimestep); - } + comm->maxforward_fix = comm->maxreverse_fix = 0; + for (i = 0; i < nfix; i++) fix[i]->init(); + + // init each compute + // add initial step to ALL computes that store invocation times + + for (i = 0; i < ncompute; i++) compute[i]->init(); + modify->addstep_compute_all(update->ntimestep); } /* ---------------------------------------------------------------------- @@ -352,7 +350,7 @@ void Modify::add_fix(int narg, char **arg) error->all("Fix command before simulation box is defined"); if (narg < 3) error->all("Illegal fix command"); - // find group ID + // check group ID int igroup = group->find(arg[1]); if (igroup == -1) error->all("Could not find fix group ID"); @@ -501,13 +499,11 @@ void Modify::add_compute(int narg, char **arg) { if (narg < 3) error->all("Illegal compute command"); - // error checks + // error check for (int icompute = 0; icompute < ncompute; icompute++) if (strcmp(arg[0],compute[icompute]->id) == 0) error->all("Reuse of compute ID"); - int igroup = group->find(arg[1]); - if (igroup == -1) error->all("Could not find compute group ID"); // extend Compute list if necessary @@ -581,28 +577,39 @@ int Modify::find_compute(char *id) } /* ---------------------------------------------------------------------- - loop over computes that store invocation times - clear their invoked flag - called by classes that invoke computes + clear invoked flag of all computes + always called before computes are invoked ------------------------------------------------------------------------- */ void Modify::clearstep_compute() { - for (int icompute = 0; icompute < n_timeflag; icompute++) - compute[list_timeflag[icompute]]->invoked = 0; + for (int icompute = 0; icompute < ncompute; icompute++) + compute[icompute]->invoked = 0; } /* ---------------------------------------------------------------------- - loop over computes that store invocation times + loop only over computes that store invocation times if it was invoked, schedule the next invocation - called by classes that invoke computes + always called after computes are invoked ------------------------------------------------------------------------- */ void Modify::addstep_compute(int ntimestep) { for (int icompute = 0; icompute < n_timeflag; icompute++) if (compute[list_timeflag[icompute]]->invoked) - compute[list_timeflag[icompute]]->add_step(ntimestep); + compute[list_timeflag[icompute]]->addstep(ntimestep); +} + +/* ---------------------------------------------------------------------- + loop only all computes + schedule the next invocation for those that store invocation times +------------------------------------------------------------------------- */ + +void Modify::addstep_compute_all(int ntimestep) +{ + for (int icompute = 0; icompute < ncompute; icompute++) + if (compute[icompute]->timeflag) + compute[icompute]->addstep(ntimestep); } /* ---------------------------------------------------------------------- diff --git a/src/modify.h b/src/modify.h index d228552c7b..79f6cbddba 100644 --- a/src/modify.h +++ b/src/modify.h @@ -67,6 +67,7 @@ class Modify : protected Pointers { int find_compute(char *); void clearstep_compute(); void addstep_compute(int); + void addstep_compute_all(int); void write_restart(FILE *); int read_restart(FILE *); diff --git a/src/output.cpp b/src/output.cpp index de9d504a85..7d7f44263d 100644 --- a/src/output.cpp +++ b/src/output.cpp @@ -133,6 +133,7 @@ void Output::setup(int flag) // will not write on last step of run unless multiple of every // set next_dump_any to smallest next_dump // if no dumps, set next_dump_any to last+1 so will not influence next + // dump custom may invoke computes so wrap with clear/add if (ndump) { for (int idump = 0; idump < ndump; idump++) { @@ -168,6 +169,7 @@ void Output::setup(int flag) // always do thermo with header at start of run // set next_thermo to multiple of every or last step of run (if smaller) // if every = 0, set next_thermo to last step of run + // thermo may invoke computes so wrap with clear/add modify->clearstep_compute(); @@ -197,6 +199,7 @@ void Output::setup(int flag) void Output::write(int ntimestep) { // next_dump does not force output on last step of run + // dump custom may invoke computes so wrap with clear/add if (next_dump_any == ntimestep) { for (int idump = 0; idump < ndump; idump++) { @@ -238,6 +241,7 @@ void Output::write(int ntimestep) } // insure next_thermo forces output on last step of run + // thermo may invoke computes so wrap with clear/add if (next_thermo == ntimestep && last_thermo != ntimestep) { modify->clearstep_compute(); diff --git a/src/pair.cpp b/src/pair.cpp index 4b177c7090..733a886562 100644 --- a/src/pair.cpp +++ b/src/pair.cpp @@ -699,7 +699,6 @@ void Pair::write_file(int narg, char **arg) double r,e,f,rsq; float rsq_float; int *int_rsq = (int *) &rsq_float; - One one; for (int i = 0; i < n; i++) { if (style == R) { @@ -720,9 +719,8 @@ void Pair::write_file(int narg, char **arg) } if (rsq < cutsq[itype][jtype]) { - single(0,1,itype,jtype,rsq,1.0,1.0,1,one); - e = one.eng_coul + one.eng_vdwl; - f = r * one.fforce; + e = single(0,1,itype,jtype,rsq,1.0,1.0,f); + f *= r; } else e = f = 0.0; if (me == 0) fprintf(fp,"%d %g %g %g\n",i+1,r,e,f); } diff --git a/src/pair.h b/src/pair.h index 28ff5ec3be..7a7c47efca 100644 --- a/src/pair.h +++ b/src/pair.h @@ -50,11 +50,6 @@ class Pair : protected Pointers { class NeighList *listmiddle; class NeighList *listouter; - struct One { // single interaction between 2 atoms - double fforce; - double eng_vdwl,eng_coul; - }; - Pair(class LAMMPS *); virtual ~Pair(); @@ -74,8 +69,8 @@ class Pair : protected Pointers { virtual void compute_middle() {} virtual void compute_outer(int, int) {} - virtual void single(int, int, int, int, - double, double, double, int, One &) {} + virtual double single(int, int, int, int, + double, double, double, double &) {return 0.0;} virtual void settings(int, char **) = 0; virtual void coeff(int, char **) = 0; diff --git a/src/pair_buck.cpp b/src/pair_buck.cpp index a00fe69e7d..4a9512610a 100644 --- a/src/pair_buck.cpp +++ b/src/pair_buck.cpp @@ -325,9 +325,9 @@ void PairBuck::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairBuck::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, double factor_lj, - int eflag, One &one) +double PairBuck::single(int i, int j, int itype, int jtype, + double rsq, double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,r,rexp,forcebuck,phibuck; @@ -336,12 +336,9 @@ void PairBuck::single(int i, int j, int itype, int jtype, r = sqrt(rsq); rexp = exp(-r*rhoinv[itype][jtype]); forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv; - one.fforce = factor_lj*forcebuck*r2inv; + fforce = factor_lj*forcebuck*r2inv; - if (eflag) { - phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*phibuck; - one.eng_coul = 0.0; - } + phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv - + offset[itype][jtype]; + return factor_lj*phibuck; } diff --git a/src/pair_buck.h b/src/pair_buck.h index a4a1e444d9..9f723820f3 100644 --- a/src/pair_buck.h +++ b/src/pair_buck.h @@ -30,7 +30,7 @@ class PairBuck : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_global; diff --git a/src/pair_buck_coul_cut.cpp b/src/pair_buck_coul_cut.cpp index bd83e30390..297e609c38 100644 --- a/src/pair_buck_coul_cut.cpp +++ b/src/pair_buck_coul_cut.cpp @@ -386,9 +386,10 @@ void PairBuckCoulCut::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairBuckCoulCut::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, double factor_lj, - int eflag, One &one) +double PairBuckCoulCut::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,r,rexp,forcecoul,forcebuck,phicoul,phibuck; @@ -402,17 +403,17 @@ void PairBuckCoulCut::single(int i, int j, int itype, int jtype, rexp = exp(-r*rhoinv[itype][jtype]); forcebuck = buck1[itype][jtype]*r*rexp - buck2[itype][jtype]*r6inv; } else forcebuck = 0.0; - one.fforce = (factor_coul*forcecoul + factor_lj*forcebuck) * r2inv; + fforce = (factor_coul*forcecoul + factor_lj*forcebuck) * r2inv; - if (eflag) { - if (rsq < cut_coulsq[itype][jtype]) { - phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); - one.eng_coul = factor_coul*phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq[itype][jtype]) { - phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*phibuck; - } else one.eng_vdwl = 0.0; + double eng = 0.0; + if (rsq < cut_coulsq[itype][jtype]) { + phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); + eng += factor_coul*phicoul; } + if (rsq < cut_ljsq[itype][jtype]) { + phibuck = a[itype][jtype]*rexp - c[itype][jtype]*r6inv - + offset[itype][jtype]; + eng += factor_lj*phibuck; + } + return eng; } diff --git a/src/pair_buck_coul_cut.h b/src/pair_buck_coul_cut.h index 06fd27c781..5f137e688b 100644 --- a/src/pair_buck_coul_cut.h +++ b/src/pair_buck_coul_cut.h @@ -31,7 +31,7 @@ class PairBuckCoulCut : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_lj_global,cut_coul_global; diff --git a/src/pair_coul_cut.cpp b/src/pair_coul_cut.cpp index 6296a47512..f01c02a011 100644 --- a/src/pair_coul_cut.cpp +++ b/src/pair_coul_cut.cpp @@ -285,20 +285,17 @@ void PairCoulCut::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairCoulCut::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, double factor_lj, - int eflag, One &one) +double PairCoulCut::single(int i, int j, int itype, int jtype, + double rsq, double factor_coul, double factor_lj, + double &fforce) { double r2inv,rinv,forcecoul,phicoul; r2inv = 1.0/rsq; rinv = sqrt(r2inv); forcecoul = force->qqrd2e * atom->q[i]*atom->q[j]*rinv; - one.fforce = factor_coul*forcecoul * r2inv; + fforce = factor_coul*forcecoul * r2inv; - if (eflag) { - phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*rinv; - one.eng_coul = factor_coul*phicoul; - one.eng_vdwl = 0.0; - } + phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*rinv; + return factor_coul*phicoul; } diff --git a/src/pair_coul_cut.h b/src/pair_coul_cut.h index 9b6a0fca49..99902b2ff8 100644 --- a/src/pair_coul_cut.h +++ b/src/pair_coul_cut.h @@ -31,7 +31,7 @@ class PairCoulCut : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_global; diff --git a/src/pair_hybrid.cpp b/src/pair_hybrid.cpp index 94c0d2b554..9c718f5c8a 100644 --- a/src/pair_hybrid.cpp +++ b/src/pair_hybrid.cpp @@ -549,28 +549,24 @@ void PairHybrid::read_restart(FILE *fp) since overlay could have multiple sub-styles, sum results explicitly ------------------------------------------------------------------------- */ -void PairHybrid::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, double factor_lj, - int eflag, One &one) +double PairHybrid::single(int i, int j, int itype, int jtype, + double rsq, double factor_coul, double factor_lj, + double &fforce) { if (nmap[itype][jtype] == 0) error->one("Invoked pair single on pair style none"); - double fforce = 0.0; - double evdwl = 0.0; - double ecoul = 0.0; + double fone; + fforce = 0.0; + double esum = 0.0; for (int m = 0; m < nmap[itype][jtype]; m++) { - styles[map[itype][jtype][m]]-> - single(i,j,itype,jtype,rsq,factor_coul,factor_lj,eflag,one); - fforce += one.fforce; - evdwl += one.eng_vdwl; - ecoul += one.eng_coul; + esum += styles[map[itype][jtype][m]]-> + single(i,j,itype,jtype,rsq,factor_coul,factor_lj,fone); + fforce += fone; } - one.fforce = fforce; - one.eng_vdwl = evdwl; - one.eng_coul = ecoul; + return esum; } /* ---------------------------------------------------------------------- diff --git a/src/pair_hybrid.h b/src/pair_hybrid.h index df80b4ba9a..68b1ea35d1 100644 --- a/src/pair_hybrid.h +++ b/src/pair_hybrid.h @@ -34,7 +34,7 @@ class PairHybrid : public Pair { double init_one(int, int); void write_restart(FILE *); void read_restart(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void modify_params(int narg, char **arg); double memory_usage(); diff --git a/src/pair_lj_cut.cpp b/src/pair_lj_cut.cpp index ebd3c1a586..403cb1a1c1 100644 --- a/src/pair_lj_cut.cpp +++ b/src/pair_lj_cut.cpp @@ -697,21 +697,18 @@ void PairLJCut::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJCut::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairLJCut::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,forcelj,philj; r2inv = 1.0/rsq; r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); - one.fforce = factor_lj*forcelj*r2inv; + fforce = factor_lj*forcelj*r2inv; - if (eflag) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - one.eng_coul = 0.0; - } + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - + offset[itype][jtype]; + return factor_lj*philj; } diff --git a/src/pair_lj_cut.h b/src/pair_lj_cut.h index a91dec05ab..ab6f7d0ceb 100644 --- a/src/pair_lj_cut.h +++ b/src/pair_lj_cut.h @@ -32,7 +32,7 @@ class PairLJCut : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void compute_inner(); void compute_middle(); diff --git a/src/pair_lj_cut_coul_cut.cpp b/src/pair_lj_cut_coul_cut.cpp index ea718d029c..1d293039c0 100644 --- a/src/pair_lj_cut_coul_cut.cpp +++ b/src/pair_lj_cut_coul_cut.cpp @@ -406,9 +406,10 @@ void PairLJCutCoulCut::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJCutCoulCut::single(int i, int j, int itype, int jtype, - double rsq, double factor_coul, double factor_lj, - int eflag, One &one) +double PairLJCutCoulCut::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,forcecoul,forcelj,phicoul,philj; @@ -420,17 +421,18 @@ void PairLJCutCoulCut::single(int i, int j, int itype, int jtype, r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; - one.fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; + fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; - if (eflag) { - if (rsq < cut_coulsq[itype][jtype]) { - phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); - one.eng_coul = factor_coul*phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq[itype][jtype]) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + double eng = 0.0; + if (rsq < cut_coulsq[itype][jtype]) { + phicoul = force->qqrd2e * atom->q[i]*atom->q[j]*sqrt(r2inv); + eng += factor_coul*phicoul; } + if (rsq < cut_ljsq[itype][jtype]) { + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - + offset[itype][jtype]; + eng += factor_lj*philj; + } + + return eng; } diff --git a/src/pair_lj_cut_coul_cut.h b/src/pair_lj_cut_coul_cut.h index 8af68331cb..ecfb685356 100644 --- a/src/pair_lj_cut_coul_cut.h +++ b/src/pair_lj_cut_coul_cut.h @@ -31,7 +31,7 @@ class PairLJCutCoulCut : public Pair { virtual void read_restart(FILE *); virtual void write_restart_settings(FILE *); virtual void read_restart_settings(FILE *); - virtual void single(int, int, int, int, double, double, double, int, One &); + virtual double single(int, int, int, int, double, double, double, double &); protected: double cut_lj_global,cut_coul_global; diff --git a/src/pair_lj_cut_coul_debye.cpp b/src/pair_lj_cut_coul_debye.cpp index 2b41c480f1..9e82be733a 100644 --- a/src/pair_lj_cut_coul_debye.cpp +++ b/src/pair_lj_cut_coul_debye.cpp @@ -243,9 +243,10 @@ void PairLJCutCoulDebye::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJCutCoulDebye::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, - int eflag, One &one) +double PairLJCutCoulDebye::single(int i, int j, int itype, int jtype, + double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,r,rinv,screening,forcecoul,forcelj,phicoul,philj; @@ -261,17 +262,18 @@ void PairLJCutCoulDebye::single(int i, int j, int itype, int jtype, double rsq, r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); } else forcelj = 0.0; - one.fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; - - if (eflag) { - if (rsq < cut_coulsq[itype][jtype]) { - phicoul = force->qqrd2e * atom->q[i]*atom->q[j] * rinv * screening; - one.eng_coul = factor_coul*phicoul; - } else one.eng_coul = 0.0; - if (rsq < cut_ljsq[itype][jtype]) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - } else one.eng_vdwl = 0.0; + fforce = (factor_coul*forcecoul + factor_lj*forcelj) * r2inv; + + double eng = 0.0; + if (rsq < cut_coulsq[itype][jtype]) { + phicoul = force->qqrd2e * atom->q[i]*atom->q[j] * rinv * screening; + eng += factor_coul*phicoul; } + if (rsq < cut_ljsq[itype][jtype]) { + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - + offset[itype][jtype]; + eng += factor_lj*philj; + } + + return eng; } diff --git a/src/pair_lj_cut_coul_debye.h b/src/pair_lj_cut_coul_debye.h index 7acdee3e7d..2646e7ed2f 100644 --- a/src/pair_lj_cut_coul_debye.h +++ b/src/pair_lj_cut_coul_debye.h @@ -27,7 +27,7 @@ class PairLJCutCoulDebye : public PairLJCutCoulCut { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double kappa; diff --git a/src/pair_lj_expand.cpp b/src/pair_lj_expand.cpp index ce14a27574..d3a50c37e6 100644 --- a/src/pair_lj_expand.cpp +++ b/src/pair_lj_expand.cpp @@ -376,9 +376,9 @@ void PairLJExpand::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJExpand::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairLJExpand::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r,rshift,rshiftsq,r2inv,r6inv,forcelj,philj; @@ -388,12 +388,9 @@ void PairLJExpand::single(int i, int j, int itype, int jtype, double rsq, r2inv = 1.0/rshiftsq; r6inv = r2inv*r2inv*r2inv; forcelj = r6inv * (lj1[itype][jtype]*r6inv - lj2[itype][jtype]); - one.fforce = factor_lj*forcelj/rshift/r; + fforce = factor_lj*forcelj/rshift/r; - if (eflag) { - philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - one.eng_coul = 0.0; - } + philj = r6inv*(lj3[itype][jtype]*r6inv-lj4[itype][jtype]) - + offset[itype][jtype]; + return factor_lj*philj; } diff --git a/src/pair_lj_expand.h b/src/pair_lj_expand.h index 845fec0c48..65cf6186b3 100644 --- a/src/pair_lj_expand.h +++ b/src/pair_lj_expand.h @@ -30,7 +30,7 @@ class PairLJExpand : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_global; diff --git a/src/pair_lj_smooth.cpp b/src/pair_lj_smooth.cpp index cc6c75798b..76dc216fbf 100644 --- a/src/pair_lj_smooth.cpp +++ b/src/pair_lj_smooth.cpp @@ -406,9 +406,9 @@ void PairLJSmooth::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairLJSmooth::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairLJSmooth::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r6inv,forcelj,philj,r,t,tsq,fskin; @@ -424,17 +424,14 @@ void PairLJSmooth::single(int i, int j, int itype, int jtype, double rsq, ljsw3[itype][jtype]*tsq + ljsw4[itype][jtype]*tsq*t; forcelj = fskin*r; } - one.fforce = factor_lj*forcelj*r2inv; + fforce = factor_lj*forcelj*r2inv; - if (eflag) { - if (rsq < cut_inner_sq[itype][jtype]) - philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]) - - offset[itype][jtype]; - else - philj = ljsw0[itype][jtype] - ljsw1[itype][jtype]*t - - ljsw2[itype][jtype]*tsq/2.0 - ljsw3[itype][jtype]*tsq*t/3.0 - - ljsw4[itype][jtype]*tsq*tsq/4.0 - offset[itype][jtype]; - one.eng_vdwl = factor_lj*philj; - one.eng_coul = 0.0; - } + if (rsq < cut_inner_sq[itype][jtype]) + philj = r6inv * (lj3[itype][jtype]*r6inv - lj4[itype][jtype]) - + offset[itype][jtype]; + else + philj = ljsw0[itype][jtype] - ljsw1[itype][jtype]*t - + ljsw2[itype][jtype]*tsq/2.0 - ljsw3[itype][jtype]*tsq*t/3.0 - + ljsw4[itype][jtype]*tsq*tsq/4.0 - offset[itype][jtype]; + return factor_lj*philj; } diff --git a/src/pair_lj_smooth.h b/src/pair_lj_smooth.h index f050199c54..641f5b2a44 100644 --- a/src/pair_lj_smooth.h +++ b/src/pair_lj_smooth.h @@ -30,7 +30,7 @@ class PairLJSmooth : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_inner_global,cut_global; diff --git a/src/pair_morse.cpp b/src/pair_morse.cpp index 3da5c26d32..f6f1858c87 100644 --- a/src/pair_morse.cpp +++ b/src/pair_morse.cpp @@ -315,20 +315,17 @@ void PairMorse::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairMorse::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairMorse::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r,dr,dexp,phi; r = sqrt(rsq); dr = r - r0[itype][jtype]; dexp = exp(-alpha[itype][jtype] * dr); - one.fforce = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r; + fforce = factor_lj * morse1[itype][jtype] * (dexp*dexp - dexp) / r; - if (eflag) { - phi = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) - offset[itype][jtype]; - one.eng_vdwl = factor_lj*phi; - one.eng_coul = 0.0; - } + phi = d0[itype][jtype] * (dexp*dexp - 2.0*dexp) - offset[itype][jtype]; + return factor_lj*phi; } diff --git a/src/pair_morse.h b/src/pair_morse.h index fa28b42e47..1f4f96b573 100644 --- a/src/pair_morse.h +++ b/src/pair_morse.h @@ -30,7 +30,7 @@ class PairMorse : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); protected: double cut_global; diff --git a/src/pair_soft.cpp b/src/pair_soft.cpp index d9e2bf69af..3f9d737288 100644 --- a/src/pair_soft.cpp +++ b/src/pair_soft.cpp @@ -326,20 +326,17 @@ void PairSoft::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairSoft::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairSoft::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r,arg,philj; r = sqrt(rsq); arg = PI*r/cut[itype][jtype]; - one.fforce = factor_lj * prefactor[itype][jtype] * + fforce = factor_lj * prefactor[itype][jtype] * sin(arg) * PI/cut[itype][jtype]/r; - if (eflag) { - philj = prefactor[itype][jtype] * (1.0+cos(arg)); - one.eng_vdwl = factor_lj*philj; - one.eng_coul = 0.0; - } + philj = prefactor[itype][jtype] * (1.0+cos(arg)); + return factor_lj*philj; } diff --git a/src/pair_soft.h b/src/pair_soft.h index 437e93dd7d..f4996864c1 100644 --- a/src/pair_soft.h +++ b/src/pair_soft.h @@ -32,7 +32,7 @@ class PairSoft : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double PI; diff --git a/src/pair_table.cpp b/src/pair_table.cpp index 0ba6e359ff..51f8f058a9 100644 --- a/src/pair_table.cpp +++ b/src/pair_table.cpp @@ -908,9 +908,9 @@ void PairTable::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairTable::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, int eflag, - One &one) +double PairTable::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { int itable; double fraction,value,a,b,phi; @@ -921,13 +921,13 @@ void PairTable::single(int i, int j, int itype, int jtype, double rsq, if (tabstyle == LOOKUP) { itable = static_cast ((rsq-tb->innersq) * tb->invdelta); if (itable >= nm1) error->one("Pair distance > table outer cutoff"); - one.fforce = factor_lj * tb->f[itable]; + fforce = factor_lj * tb->f[itable]; } else if (tabstyle == LINEAR) { itable = static_cast ((rsq-tb->innersq) * tb->invdelta); if (itable >= nm1) error->one("Pair distance > table outer cutoff"); fraction = (rsq - tb->rsq[itable]) * tb->invdelta; value = tb->f[itable] + fraction*tb->df[itable]; - one.fforce = factor_lj * value; + fforce = factor_lj * value; } else if (tabstyle == SPLINE) { itable = static_cast ((rsq-tb->innersq) * tb->invdelta); if (itable >= nm1) error->one("Pair distance > table outer cutoff"); @@ -936,7 +936,7 @@ void PairTable::single(int i, int j, int itype, int jtype, double rsq, value = a * tb->f[itable] + b * tb->f[itable+1] + ((a*a*a-a)*tb->f2[itable] + (b*b*b-b)*tb->f2[itable+1]) * tb->deltasq6; - one.fforce = factor_lj * value; + fforce = factor_lj * value; } else { float rsq_single = rsq; int *int_rsq = (int *) &rsq_single; @@ -944,20 +944,17 @@ void PairTable::single(int i, int j, int itype, int jtype, double rsq, itable >>= tb->nshiftbits; fraction = (rsq_single - tb->rsq[itable]) * tb->drsq[itable]; value = tb->f[itable] + fraction*tb->df[itable]; - one.fforce = factor_lj * value; + fforce = factor_lj * value; } - if (eflag) { - if (tabstyle == LOOKUP) - phi = tb->e[itable]; - else if (tabstyle == LINEAR || tabstyle == BITMAP) - phi = tb->e[itable] + fraction*tb->de[itable]; - else - phi = a * tb->e[itable] + b * tb->e[itable+1] + - ((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) * tb->deltasq6; - one.eng_vdwl = factor_lj*phi; - one.eng_coul = 0.0; - } + if (tabstyle == LOOKUP) + phi = tb->e[itable]; + else if (tabstyle == LINEAR || tabstyle == BITMAP) + phi = tb->e[itable] + fraction*tb->de[itable]; + else + phi = a * tb->e[itable] + b * tb->e[itable+1] + + ((a*a*a-a)*tb->e2[itable] + (b*b*b-b)*tb->e2[itable+1]) * tb->deltasq6; + return factor_lj*phi; } /* ---------------------------------------------------------------------- diff --git a/src/pair_table.h b/src/pair_table.h index 2c02872bb7..9b1b9bf770 100644 --- a/src/pair_table.h +++ b/src/pair_table.h @@ -30,7 +30,7 @@ class PairTable : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); void *extract(char *); private: diff --git a/src/pair_yukawa.cpp b/src/pair_yukawa.cpp index 200df3c47f..69a88ff0b0 100644 --- a/src/pair_yukawa.cpp +++ b/src/pair_yukawa.cpp @@ -300,9 +300,9 @@ void PairYukawa::read_restart_settings(FILE *fp) /* ---------------------------------------------------------------------- */ -void PairYukawa::single(int i, int j, int itype, int jtype, double rsq, - double factor_coul, double factor_lj, - int eflag, One &one) +double PairYukawa::single(int i, int j, int itype, int jtype, double rsq, + double factor_coul, double factor_lj, + double &fforce) { double r2inv,r,rinv,screening,forceyukawa,phi; @@ -311,11 +311,8 @@ void PairYukawa::single(int i, int j, int itype, int jtype, double rsq, rinv = 1.0/r; screening = exp(-kappa*r); forceyukawa = a[itype][jtype] * screening * (kappa + rinv); - one.fforce = factor_coul*forceyukawa * r2inv; + fforce = factor_coul*forceyukawa * r2inv; - if (eflag) { - phi = a[itype][jtype] * screening * rinv - offset[itype][jtype]; - one.eng_coul = factor_coul*phi; - one.eng_vdwl = 0.0; - } + phi = a[itype][jtype] * screening * rinv - offset[itype][jtype]; + return factor_coul*phi; } diff --git a/src/pair_yukawa.h b/src/pair_yukawa.h index 0724be1456..a8a84fc83f 100644 --- a/src/pair_yukawa.h +++ b/src/pair_yukawa.h @@ -30,7 +30,7 @@ class PairYukawa : public Pair { void read_restart(FILE *); void write_restart_settings(FILE *); void read_restart_settings(FILE *); - void single(int, int, int, int, double, double, double, int, One &); + double single(int, int, int, int, double, double, double, double &); private: double cut_global; diff --git a/src/run.cpp b/src/run.cpp index 89aa494c8b..8ececad10e 100644 --- a/src/run.cpp +++ b/src/run.cpp @@ -192,10 +192,10 @@ void Run::command(int narg, char **arg) update->integrate->cleanup(); Finish finish(lmp); - if (postflag || nleft == 0) finish.end(1); + if (postflag || nleft <= nsteps) finish.end(1); else finish.end(0); - // command string may invoke a compute that affects Verlet::eflag,vflag + // command string may invoke computes so wrap with clear/add if (commandstr) { modify->clearstep_compute(); diff --git a/src/style.h b/src/style.h index 5d03f7a4b7..e07a04103d 100644 --- a/src/style.h +++ b/src/style.h @@ -76,7 +76,6 @@ CommandStyle(write_restart,WriteRestart) #endif #ifdef ComputeInclude -#include "compute_attribute_atom.h" #include "compute_centro_atom.h" #include "compute_coord_atom.h" #include "compute_ke_atom.h" @@ -87,18 +86,14 @@ CommandStyle(write_restart,WriteRestart) #include "compute_rotate_gran.h" #include "compute_stress_atom.h" #include "compute_sum.h" -#include "compute_sum_atom.h" #include "compute_temp.h" #include "compute_temp_deform.h" #include "compute_temp_partial.h" #include "compute_temp_ramp.h" #include "compute_temp_region.h" -#include "compute_variable.h" -#include "compute_variable_atom.h" #endif #ifdef ComputeClass -ComputeStyle(attribute/atom,ComputeAttributeAtom) ComputeStyle(centro/atom,ComputeCentroAtom) ComputeStyle(coord/atom,ComputeCoordAtom) ComputeStyle(ke/atom,ComputeKEAtom) @@ -109,14 +104,11 @@ ComputeStyle(rotate/dipole,ComputeRotateDipole) ComputeStyle(rotate/gran,ComputeRotateGran) ComputeStyle(stress/atom,ComputeStressAtom) ComputeStyle(sum,ComputeSum) -ComputeStyle(sum/atom,ComputeSumAtom) ComputeStyle(temp,ComputeTemp) ComputeStyle(temp/deform,ComputeTempDeform) ComputeStyle(temp/partial,ComputeTempPartial) ComputeStyle(temp/ramp,ComputeTempRamp) ComputeStyle(temp/region,ComputeTempRegion) -ComputeStyle(variable,ComputeVariable) -ComputeStyle(variable/atom,ComputeVariableAtom) #endif #ifdef DihedralInclude diff --git a/src/temper.cpp b/src/temper.cpp index 730ac4bf6e..fea8f30e4c 100644 --- a/src/temper.cpp +++ b/src/temper.cpp @@ -125,7 +125,7 @@ void Temper::command(int narg, char **arg) int id = modify->find_compute("thermo_pe"); if (id < 0) error->all("Tempering could not find thermo_pe compute"); Compute *pe_compute = modify->compute[id]; - pe_compute->add_step(update->ntimestep + nevery); + pe_compute->addstep(update->ntimestep + nevery); // create MPI communicator for root proc from each world @@ -209,7 +209,7 @@ void Temper::command(int narg, char **arg) pe = pe_compute->compute_scalar(); if (output->thermo->normflag) pe /= atom->natoms; - pe_compute->add_step(update->ntimestep + nevery); + pe_compute->addstep(update->ntimestep + nevery); // which = which of 2 kinds of swaps to do (0,1) diff --git a/src/thermo.cpp b/src/thermo.cpp index 01b0559b65..aeb684821a 100644 --- a/src/thermo.cpp +++ b/src/thermo.cpp @@ -58,7 +58,13 @@ enum{ONELINE,MULTILINE}; enum{INT,FLOAT}; #define MAXLINE 1024 -#define DELTA 8 +#define DELTA 8 + +#define MIN(A,B) ((A) < (B)) ? (A) : (B) +#define MAX(A,B) ((A) > (B)) ? (A) : (B) + +#define INVOKED_SCALAR 1 // same as in computes +#define INVOKED_VECTOR 2 /* ---------------------------------------------------------------------- */ @@ -245,6 +251,15 @@ void Thermo::init() error->all("Thermo and fix not computed at compatible times"); } + // find current ptr for each Variable ID + + int ivariable; + for (i = 0; i < nvariable; i++) { + ivariable = input->variable->find(id_variable[i]); + if (ivariable < 0) error->all("Could not find thermo variable name"); + variables[i] = ivariable; + } + // set ptrs to keyword-specific Compute objects if (index_temp >= 0) temperature = computes[index_temp]; @@ -287,11 +302,16 @@ void Thermo::compute(int flag) else normflag = normvalue; // invoke Compute methods needed for thermo keywords - // call compute_scalar() if which = 0, else compute_vector() + // which = 0 is global scalar, which = 1 is global vector for (i = 0; i < ncompute; i++) { - if (compute_which[i] % 2 == 0) double tmp = computes[i]->compute_scalar(); - if (compute_which[i] > 0) computes[i]->compute_vector(); + if (compute_which[i] == 0) { + if (!(computes[i]->invoked & INVOKED_SCALAR)) + double tmp = computes[i]->compute_scalar(); + } else { + if (!(computes[i]->invoked & INVOKED_VECTOR)) + computes[i]->compute_vector(); + } } // if lineflag = MULTILINE, prepend step/cpu header line @@ -389,7 +409,7 @@ void Thermo::modify_params(int narg, char **arg) if (temperature->igroup != 0 && comm->me == 0) error->warning("Temperature for thermo pressure is not for group all"); - // reset id_pre[0] of pressure to new temp ID + // reset id_pre of pressure to new temp ID // either pressure currently being used by thermo or "thermo_pressure" if (index_press >= 0) { @@ -397,9 +417,9 @@ void Thermo::modify_params(int narg, char **arg) if (icompute < 0) error->all("Press ID for thermo does not exist"); } else icompute = modify->find_compute((char *) "thermo_pressure"); - delete [] modify->compute[icompute]->id_pre[0]; - modify->compute[icompute]->id_pre[0] = new char[n]; - strcpy(modify->compute[icompute]->id_pre[0],arg[iarg+1]); + delete [] modify->compute[icompute]->id_pre; + modify->compute[icompute]->id_pre = new char[n]; + strcpy(modify->compute[icompute]->id_pre,arg[iarg+1]); iarg += 2; @@ -418,23 +438,6 @@ void Thermo::modify_params(int narg, char **arg) if (pressure->pressflag == 0) error->all("Thermo_modify press ID does not compute pressure"); - // if id_pre[0] of new pressure not being computed, add to compute list - // swap it with pressure in list so id_pre[0] will be computed first - // OK to call add_compute with "which" acting as index - - int which = compute_which[index_press]; - int ncompute_current = ncompute; - icompute = add_compute(pressure->id_pre[0],which); - if (icompute == ncompute_current) { - int iswap = compute_which[index_press]; - compute_which[index_press] = compute_which[icompute]; - compute_which[icompute] = iswap; - char *cswap = id_compute[index_press]; - id_compute[index_press] = id_compute[icompute]; - id_compute[icompute] = cswap; - index_press = icompute; - } - iarg += 2; } else if (strcmp(arg[iarg],"drot") == 0) { @@ -546,13 +549,15 @@ void Thermo::allocate() format_user = new char*[n]; for (int i = 0; i < n; i++) format_user[i] = NULL; - field2object = new int[n]; - arg_object = new int[n]; + field2index = new int[n]; + argindex = new int[n]; + + // factor of 3 is max number of computes a single field can add ncompute = 0; - id_compute = NULL; - compute_which = NULL; - computes = NULL; + id_compute = new char*[3*n]; + compute_which = new int[3*n]; + computes = new Compute*[3*n]; nfix = 0; id_fix = new char*[n]; @@ -560,6 +565,7 @@ void Thermo::allocate() nvariable = 0; id_variable = new char*[n]; + variables = new int[n]; } /* ---------------------------------------------------------------------- @@ -580,13 +586,13 @@ void Thermo::deallocate() for (int i = 0; i < n; i++) delete [] format_user[i]; delete [] format_user; - delete [] field2object; - delete [] arg_object; + delete [] field2index; + delete [] argindex; for (int i = 0; i < ncompute; i++) delete [] id_compute[i]; - memory->sfree(id_compute); - memory->sfree(compute_which); - memory->sfree(computes); + delete [] id_compute; + delete [] compute_which; + delete [] computes; for (int i = 0; i < nfix; i++) delete [] id_fix[i]; delete [] id_fix; @@ -594,6 +600,7 @@ void Thermo::deallocate() for (int i = 0; i < nvariable; i++) delete [] id_variable[i]; delete [] id_variable; + delete [] variables; } /* ---------------------------------------------------------------------- @@ -622,7 +629,6 @@ void Thermo::parse_fields(char *str) index_temp = add_compute(id_temp,0); } else if (strcmp(word,"press") == 0) { addfield("Press",&Thermo::compute_press,FLOAT); - index_temp = add_compute(id_temp,0); index_press = add_compute(id_press,0); } else if (strcmp(word,"pe") == 0) { addfield("PotEng",&Thermo::compute_pe,FLOAT); @@ -695,27 +701,21 @@ void Thermo::parse_fields(char *str) } else if (strcmp(word,"pxx") == 0) { addfield("Pxx",&Thermo::compute_pxx,FLOAT); - index_temp = add_compute(id_temp,1); index_press = add_compute(id_press,1); } else if (strcmp(word,"pyy") == 0) { addfield("Pyy",&Thermo::compute_pyy,FLOAT); - index_temp = add_compute(id_temp,1); index_press = add_compute(id_press,1); } else if (strcmp(word,"pzz") == 0) { addfield("Pzz",&Thermo::compute_pzz,FLOAT); - index_temp = add_compute(id_temp,1); index_press = add_compute(id_press,1); } else if (strcmp(word,"pxy") == 0) { addfield("Pxy",&Thermo::compute_pxy,FLOAT); - index_temp = add_compute(id_temp,1); index_press = add_compute(id_press,1); } else if (strcmp(word,"pxz") == 0) { addfield("Pxz",&Thermo::compute_pxz,FLOAT); - index_temp = add_compute(id_temp,1); index_press = add_compute(id_press,1); } else if (strcmp(word,"pyz") == 0) { addfield("Pyz",&Thermo::compute_pyz,FLOAT); - index_temp = add_compute(id_temp,1); index_press = add_compute(id_press,1); } else if (strcmp(word,"drot") == 0) { @@ -728,7 +728,6 @@ void Thermo::parse_fields(char *str) // compute value = c_ID, fix value = f_ID, variable value = v_ID // if no trailing [], then arg is set to 0, else arg is between [] // copy = at most 8 chars of ID to pass to addfield - // if Compute has pre-computes, first add them to list } else if ((strncmp(word,"c_",2) == 0) || (strncmp(word,"f_",2) == 0) || (strncmp(word,"v_",2) == 0)) { @@ -744,45 +743,45 @@ void Thermo::parse_fields(char *str) if (ptr) { if (id[strlen(id)-1] != ']') error->all("Invalid keyword in thermo_style custom command"); - arg_object[nfield] = atoi(ptr+1); + argindex[nfield] = atoi(ptr+1); *ptr = '\0'; - } else arg_object[nfield] = 0; + } else argindex[nfield] = 0; if (word[0] == 'c') { n = modify->find_compute(id); if (n < 0) error->all("Could not find thermo custom compute ID"); - if (arg_object[nfield] == 0 && modify->compute[n]->scalar_flag == 0) + if (argindex[nfield] == 0 && modify->compute[n]->scalar_flag == 0) error->all("Thermo compute ID does not compute scalar info"); - if (arg_object[nfield] > 0 && modify->compute[n]->vector_flag == 0) + if (argindex[nfield] > 0 && modify->compute[n]->vector_flag == 0) error->all("Thermo compute ID does not compute vector info"); - if (arg_object[nfield] > 0 && - arg_object[nfield] > modify->compute[n]->size_vector) + if (argindex[nfield] > 0 && + argindex[nfield] > modify->compute[n]->size_vector) error->all("Thermo compute ID vector is not large enough"); - if (modify->compute[n]->npre) - for (int ic = 0; ic < modify->compute[n]->npre; ic++) - int tmp = add_compute(modify->compute[n]->id_pre[ic], - arg_object[nfield]); - field2object[nfield] = add_compute(id,arg_object[nfield]); + field2index[nfield] = add_compute(id,MIN(argindex[nfield],1)); addfield(copy,&Thermo::compute_compute,FLOAT); } else if (word[0] == 'f') { n = modify->find_fix(id); if (n < 0) error->all("Could not find thermo custom fix ID"); - if (arg_object[nfield] == 0 && modify->fix[n]->scalar_flag == 0) + if (argindex[nfield] == 0 && modify->fix[n]->scalar_flag == 0) error->all("Thermo fix ID does not compute scalar info"); - if (arg_object[nfield] > 0 && modify->fix[n]->vector_flag == 0) + if (argindex[nfield] > 0 && modify->fix[n]->vector_flag == 0) error->all("Thermo fix ID does not compute vector info"); - if (arg_object[nfield] > 0 && - arg_object[nfield] > modify->fix[n]->size_vector) + if (argindex[nfield] > 0 && + argindex[nfield] > modify->fix[n]->size_vector) error->all("Thermo fix ID vector is not large enough"); - field2object[nfield] = add_fix(id); + + field2index[nfield] = add_fix(id); addfield(copy,&Thermo::compute_fix,FLOAT); - } else { + } else if (word[0] == 'v') { n = input->variable->find(id); - if (n < 0) error->all("Could not find thermo custom variable ID"); - field2object[nfield] = add_variable(id); + if (n < 0) error->all("Could not find thermo custom variable name"); + if (input->variable->equalstyle(n) == 0) + error->all("Thermo custom variable is not equal-style variable"); + + field2index[nfield] = add_variable(id); addfield(copy,&Thermo::compute_variable,FLOAT); } @@ -809,41 +808,21 @@ void Thermo::addfield(const char *key, FnPtr func, int typeflag) /* ---------------------------------------------------------------------- add compute ID to list of Compute objects to call return location of where this Compute is in list - if already in list, do not add, just return index, else add to list - convert index into which param - index = 0 -> scalar, index >= 1 -> vector - which = 1 -> scalar only, which = 2 -> vector only, which = 3 -> both - change which param if Compute is in list with different which param + if already in list with same which, do not add, just return index ------------------------------------------------------------------------- */ -int Thermo::add_compute(const char *id, int index) +int Thermo::add_compute(const char *id, int which) { int icompute; for (icompute = 0; icompute < ncompute; icompute++) - if (strcmp(id,id_compute[icompute]) == 0) { - if (index == 0 && compute_which[icompute] == 1) - compute_which[icompute] = 2; - if (index > 0 && compute_which[icompute] == 0) - compute_which[icompute] = 2; - break; - } + if ((strcmp(id,id_compute[icompute]) == 0) && + which == compute_which[icompute]) break; if (icompute < ncompute) return icompute; - id_compute = (char **) - memory->srealloc(id_compute,(ncompute+1)*sizeof(char *), - "thermo:id_compute"); - compute_which = (int *) - memory->srealloc(compute_which,(ncompute+1)*sizeof(int), - "thermo:compute_which"); - computes = (Compute **) - memory->srealloc(computes,(ncompute+1)*sizeof(Compute *), - "thermo:computes"); - int n = strlen(id) + 1; id_compute[ncompute] = new char[n]; strcpy(id_compute[ncompute],id); - if (index == 0) compute_which[ncompute] = 0; - else compute_which[ncompute] = 1; + compute_which[ncompute] = which; ncompute++; return ncompute-1; } @@ -901,12 +880,6 @@ void Thermo::create_compute(char *id, char *cstyle, char *extra) int Thermo::evaluate_keyword(char *word, double *answer) { - // don't allow use of thermo keyword before first run - // since system is not setup (e.g. no forces have been called for energy) - - if (update->first_update == 0) - error->all("Variable equal thermo keyword used before initial run"); - // check if Compute pointers exist for keywords that need them // error if thermo style does not use the Compute @@ -948,7 +921,7 @@ int Thermo::evaluate_keyword(char *word, double *answer) strcmp(word,"elong") == 0 || strcmp(word,"etail") == 0) { if (!pe) error->all("Variable uses compute via thermo keyword that thermo does not"); - pe->invoked = 1; + pe->invoked |= INVOKED_SCALAR; } // toggle thermoflag off/on @@ -1019,42 +992,58 @@ int Thermo::evaluate_keyword(char *word, double *answer) /* ---------------------------------------------------------------------- extraction of Compute, Fix, Variable results - ignore thermoflag, since these 3 routines only called by Thermo::compute(), - not by variable evaluation - compute/fix are normalized by atoms if returning extensive value(s) - variable value is not normalized (so formula should normalize if desired) + ignore thermoflag: + 3 methods only called by Thermo::compute(), not by variable evaluation + compute/fix are normalized by atoms if returning extensive value + variable value is not normalized (formula should normalize if desired) ------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ void Thermo::compute_compute() { - int index = field2object[ifield]; - if (arg_object[ifield] == 0) dvalue = computes[index]->scalar; - else dvalue = computes[index]->vector[arg_object[ifield]-1]; - if (normflag && computes[index]->extensive) dvalue /= natoms; + Compute *compute = computes[field2index[ifield]]; + if (argindex[ifield] == 0) { + dvalue = compute->scalar; + if (normflag && compute->extscalar) dvalue /= natoms; + } else { + dvalue = compute->vector[argindex[ifield]-1]; + if (normflag) { + if (compute->extvector == 0) return; + else if (compute->extvector == 1) dvalue /= natoms; + else if (compute->extlist[argindex[ifield]-1]) dvalue /= natoms; + } + } } /* ---------------------------------------------------------------------- */ void Thermo::compute_fix() { - int index = field2object[ifield]; - if (arg_object[ifield] == 0) dvalue = fixes[index]->compute_scalar(); - else dvalue = fixes[index]->compute_vector(arg_object[ifield]-1); - if (normflag && fixes[index]->extensive) dvalue /= natoms; + Fix *fix = fixes[field2index[ifield]]; + if (argindex[ifield] == 0) { + dvalue = fix->compute_scalar(); + if (normflag && fix->extscalar) dvalue /= natoms; + } else { + dvalue = fix->compute_vector(argindex[ifield]-1); + if (normflag) { + if (fix->extvector == 0) return; + else if (fix->extvector == 1) dvalue /= natoms; + else if (fix->extlist[argindex[ifield]-1]) dvalue /= natoms; + } + } } /* ---------------------------------------------------------------------- */ void Thermo::compute_variable() { - int index = field2object[ifield]; - dvalue = atof(input->variable->retrieve(id_variable[index])); + int index = field2index[ifield]; + dvalue = input->variable->compute_equal(variables[index]); } /* ---------------------------------------------------------------------- - one routine for every thermo keyword can output + one method for every keyword thermo can output thermoflag = 1 if called by Thermo::compute() thermoflag = 0 if called by evaluate_keyword() via Variable set ivalue/dvalue if value is integer/double @@ -1086,7 +1075,8 @@ void Thermo::compute_cpu() void Thermo::compute_temp() { - if (thermoflag) dvalue = temperature->scalar; + if (thermoflag || temperature->invoked & INVOKED_SCALAR) + dvalue = temperature->scalar; else dvalue = temperature->compute_scalar(); } @@ -1094,18 +1084,17 @@ void Thermo::compute_temp() void Thermo::compute_press() { - if (thermoflag) dvalue = pressure->scalar; - else { - dvalue = temperature->compute_scalar(); - dvalue = pressure->compute_scalar(); - } + if (thermoflag || pressure->invoked & INVOKED_SCALAR) + dvalue = pressure->scalar; + else dvalue = pressure->compute_scalar(); } /* ---------------------------------------------------------------------- */ void Thermo::compute_pe() { - if (thermoflag) dvalue = pe->scalar; + if (thermoflag || pe->invoked & INVOKED_SCALAR) + dvalue = pe->scalar; else dvalue = pe->compute_scalar(); if (normflag) dvalue /= natoms; } @@ -1114,8 +1103,10 @@ void Thermo::compute_pe() void Thermo::compute_ke() { - if (thermoflag) dvalue = temperature->scalar; + if (thermoflag || temperature->invoked & INVOKED_SCALAR) + dvalue = temperature->scalar; else dvalue = temperature->compute_scalar(); + dvalue *= 0.5 * temperature->dof * force->boltz; if (normflag) dvalue /= natoms; } @@ -1127,8 +1118,10 @@ void Thermo::compute_etotal() compute_pe(); double ke; - if (thermoflag) ke = temperature->scalar; + if (thermoflag || temperature->invoked & INVOKED_SCALAR) + ke = temperature->scalar; else ke = temperature->compute_scalar(); + ke *= 0.5 * temperature->dof * force->boltz; if (normflag) ke /= natoms; dvalue += ke; @@ -1351,10 +1344,8 @@ void Thermo::compute_zhi() void Thermo::compute_pxx() { - if (!thermoflag) { - temperature->compute_vector(); + if (thermoflag == 0 && !(pressure->invoked & INVOKED_VECTOR)) pressure->compute_vector(); - } dvalue = pressure->vector[0]; } @@ -1362,10 +1353,8 @@ void Thermo::compute_pxx() void Thermo::compute_pyy() { - if (!thermoflag) { - temperature->compute_vector(); + if (thermoflag == 0 && !(pressure->invoked & INVOKED_VECTOR)) pressure->compute_vector(); - } dvalue = pressure->vector[1]; } @@ -1373,10 +1362,8 @@ void Thermo::compute_pyy() void Thermo::compute_pzz() { - if (!thermoflag) { - temperature->compute_vector(); + if (thermoflag == 0 && !(pressure->invoked & INVOKED_VECTOR)) pressure->compute_vector(); - } dvalue = pressure->vector[2]; } @@ -1384,10 +1371,8 @@ void Thermo::compute_pzz() void Thermo::compute_pxy() { - if (!thermoflag) { - temperature->compute_vector(); + if (thermoflag == 0 && !(pressure->invoked & INVOKED_VECTOR)) pressure->compute_vector(); - } dvalue = pressure->vector[3]; } @@ -1395,10 +1380,8 @@ void Thermo::compute_pxy() void Thermo::compute_pxz() { - if (!thermoflag) { - temperature->compute_vector(); + if (thermoflag == 0 && !(pressure->invoked & INVOKED_VECTOR)) pressure->compute_vector(); - } dvalue = pressure->vector[4]; } @@ -1406,10 +1389,8 @@ void Thermo::compute_pxz() void Thermo::compute_pyz() { - if (!thermoflag) { - temperature->compute_vector(); + if (thermoflag == 0 && !(pressure->invoked & INVOKED_VECTOR)) pressure->compute_vector(); - } dvalue = pressure->vector[5]; } @@ -1417,7 +1398,8 @@ void Thermo::compute_pyz() void Thermo::compute_drot() { - if (thermoflag) dvalue = rotate_dipole->scalar; + if (thermoflag || rotate_dipole->invoked & INVOKED_SCALAR) + dvalue = rotate_dipole->scalar; else dvalue = rotate_dipole->compute_scalar(); if (normflag) dvalue /= natoms; } @@ -1426,7 +1408,8 @@ void Thermo::compute_drot() void Thermo::compute_grot() { - if (thermoflag) dvalue = rotate_gran->scalar; + if (thermoflag || rotate_gran->invoked & INVOKED_SCALAR) + dvalue = rotate_gran->scalar; else dvalue = rotate_gran->compute_scalar(); if (normflag) dvalue /= natoms; } diff --git a/src/thermo.h b/src/thermo.h index 27abe296ed..3396733951 100644 --- a/src/thermo.h +++ b/src/thermo.h @@ -61,8 +61,8 @@ class Thermo : protected Pointers { double dvalue,natoms; // dvalue = double value to print int ifield; // which field in thermo output is being computed int thermoflag; // 1 when called by compute(), 0 from variable eval - int *field2object; // which object (C,F,v) computes this field - int *arg_object; // integer arg to pass to routine that computes it + int *field2index; // which compute,fix,variable calcs this field + int *argindex; // index into compute,fix scalar,vector // data for keyword-specific Compute objects // index = where they are in computes list @@ -85,6 +85,7 @@ class Thermo : protected Pointers { int nvariable; // # of variables evaulated by thermo char **id_variable; // list of variable names + int *variables; // list of Variable indices // private methods diff --git a/src/variable.cpp b/src/variable.cpp index 7bf611d29f..14d1d73716 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -33,9 +33,16 @@ using namespace LAMMPS_NS; #define VARDELTA 4 +#define MAXLEVEL 4 enum{INDEX,LOOP,EQUAL,WORLD,UNIVERSE,ULOOP,ATOM}; -enum{VALUE,ATOMARRAY,TYPEARRAY,ADD,SUB,MULT,DIV,NEG,POW,EXP,LN,SQRT}; +enum{ARG,OP}; +enum{DONE,ADD,SUBTRACT,MULTIPLY,DIVIDE,CARAT,UNARY, + SQRT,EXP,LN,VALUE,ATOMARRAY,TYPEARRAY}; + +#define INVOKED_SCALAR 1 // same as in computes +#define INVOKED_VECTOR 2 +#define INVOKED_PERATOM 4 /* ---------------------------------------------------------------------- */ @@ -49,6 +56,12 @@ Variable::Variable(LAMMPS *lmp) : Pointers(lmp) num = NULL; index = NULL; data = NULL; + + precedence[DONE] = 0; + precedence[ADD] = precedence[SUBTRACT] = 1; + precedence[MULTIPLY] = precedence[DIVIDE] = 2; + precedence[CARAT] = 3; + precedence[UNARY] = 4; } /* ---------------------------------------------------------------------- */ @@ -75,9 +88,10 @@ void Variable::set(int narg, char **arg) { if (narg < 3) error->all("Illegal variable command"); - // if var already exists, just skip, except EQUAL vars + // if var already exists, just skip, except EQUAL and ATOM vars - if (find(arg[0]) >= 0 && strcmp(arg[1],"equal") != 0) return; + if (find(arg[0]) >= 0 && + strcmp(arg[1],"equal") != 0 && strcmp(arg[1],"atom") != 0) return; // make space for new variable @@ -193,11 +207,17 @@ void Variable::set(int narg, char **arg) } // ATOM + // remove pre-existing var if also style ATOM (allows it to be reset) // num = 1, index = 1st value // data = 1 value, string to eval } else if (strcmp(arg[1],"atom") == 0) { if (narg != 3) error->all("Illegal variable command"); + if (find(arg[0]) >= 0) { + if (style[find(arg[0])] != ATOM) + error->all("Cannot redefine variable as a different style"); + remove(find(arg[0])); + } style[nvar] = ATOM; num[nvar] = 1; index[nvar] = 0; @@ -207,10 +227,17 @@ void Variable::set(int narg, char **arg) } else error->all("Illegal variable command"); // set name of variable - // must come at end, since EQUAL reset may have removed name + // must come at end, since EQUAL/ATOM reset may have removed name + // name must be all alphanumeric chars or underscores - names[nvar] = new char[strlen(arg[0]) + 1]; + int n = strlen(arg[0]) + 1; + names[nvar] = new char[n]; strcpy(names[nvar],arg[0]); + + for (int i = 0; i < n-1; i++) + if (!isalnum(names[nvar][i]) && names[nvar][i] != '_') + error->all("Variable name must be alphanumeric or underscore characters"); + nvar++; } @@ -355,6 +382,50 @@ char *Variable::retrieve(char *name) return str; } +/* ---------------------------------------------------------------------- + return result of equal-style variable evaluation +------------------------------------------------------------------------- */ + +double Variable::compute_equal(int ivar) +{ + return evaluate(data[ivar][0],NULL); +} + +/* ---------------------------------------------------------------------- + compute result of atom-style variable evaluation + stride used since result may not be contiguous memory locs + if sumflag, add variable values to existing result +------------------------------------------------------------------------- */ + +void Variable::compute_atom(int ivar, int igroup, + double *result, int stride, int sumflag) +{ + Tree *tree; + double tmp = evaluate(data[ivar][0],&tree); + + int groupbit = group->bitmask[igroup]; + int *mask = atom->mask; + int nlocal = atom->nlocal; + + if (sumflag == 0) { + int m = 0; + for (int i = 0; i < nlocal; i++) { + if (mask[i] && groupbit) result[m] = eval_tree(tree,i); + else result[m] = 0.0; + m += stride; + } + + } else { + int m = 0; + for (int i = 0; i < nlocal; i++) { + if (mask[i] && groupbit) result[m] += eval_tree(tree,i); + m += stride; + } + } + + free_tree(tree); +} + /* ---------------------------------------------------------------------- search for name in list of variables names return index or -1 if not found @@ -368,10 +439,20 @@ int Variable::find(char *name) } /* ---------------------------------------------------------------------- - return 1 if variable calculates a per-atom quantity, 0 if not + return 1 if variable is EQUAL style, 0 if not ------------------------------------------------------------------------- */ -int Variable::peratom(int ivar) +int Variable::equalstyle(int ivar) +{ + if (style[ivar] == EQUAL) return 1; + return 0; +} + +/* ---------------------------------------------------------------------- + return 1 if variable is ATOM style, 0 if not +------------------------------------------------------------------------- */ + +int Variable::atomstyle(int ivar) { if (style[ivar] == ATOM) return 1; return 0; @@ -414,502 +495,427 @@ void Variable::copy(int narg, char **from, char **to) /* ---------------------------------------------------------------------- recursive evaluation of a "string" - string is defined as one of several items: + string is a equal-style or atom-style formula containing one or more items: number = 0.0, -5.45, 2.8e-4, ... thermo keyword = ke, vol, atoms, ... - variable keyword = v_a, v_myvar, ... - math function = div(x,y), mult(x,y), add(x,y), ... - group function = mass(group), xcm(group,x), ... - atom vector = x[123], y[3], vx[34], ... - compute vector = c_mytemp[0], c_thermo_pressure[3], ... - fix vector = f_indent[0], f_setforce[3], ... - numbers start with a digit or "." or "-" (no parens or brackets) - keywords start with a lowercase letter (no parens or brackets) - functions contain () - can have 1 or 2 args, each of which can be a "string" - vectors contain [] - single arg must be integer - for atom vectors, arg is global ID of atom - for compute/fix vectors, 0 is the scalar value, 1-N are vector values - see lists of valid functions & vectors below - return answer = value of string + math operation = (),-x,x+y,x-y,x*y,x/y,x^y,sqrt(x),exp(x),ln(x) + group function = count(group), mass(group), xcm(group,x), ... + atom value = x[123], y[3], vx[34], ... + atom vector = x[], y[], vx[], ... + compute = c_mytemp, c_thermo_pressure[3], ... + fix = f_indent, f_setforce[3], ... + variable = v_a, v_myvar, ... + if tree ptr passed in, return ptr to parse tree created for formula + if no tree ptr passed in, return value of string as double ------------------------------------------------------------------------- */ -double Variable::evaluate(char *str, Tree *tree) +double Variable::evaluate(char *str, Tree **tree) { - double answer = 0.0; - if (tree) { - tree->type = VALUE; - tree->left = tree->right = NULL; - } + int op,opprevious; + double value1,value2; - // string is a "function" since contains () - // grab one or two args, separated by "," - // evaulate args recursively - // if tree = NULL, evaluate math or group function - // else store as leaf in tree + double argstack[MAXLEVEL]; + Tree *treestack[MAXLEVEL]; + int opstack[MAXLEVEL]; + int nargstack = 0; + int ntreestack = 0; + int nopstack = 0; - if (strchr(str,'(')) { - if (str[strlen(str)-1] != ')') error->all("Cannot evaluate variable"); + int i = 0; + int expect = ARG; - char *ptr = strchr(str,'('); - int n = ptr - str; - char *func = new char[n+1]; - strncpy(func,str,n); - func[n] = '\0'; + while (1) { + char onechar = str[i]; - char *comma = ++ptr; - int level = 0; - while (1) { - if (*comma == '\0') error->all("Cannot evaluate variable"); - else if (*comma == ',' && level == 0) break; - else if (*comma == ')' && level == 0) break; - else if (*comma == '(') level++; - else if (*comma == ')') level--; - comma++; - } + // whitespace: just skip - char *arg1,*arg2; - n = comma - ptr; - arg1 = new char[n+1]; - strncpy(arg1,ptr,n); - arg1[n] = '\0'; + if (isspace(onechar)) i++; - if (*comma == ',') { - ptr = comma + 1; - comma = &str[strlen(str)-1]; - n = comma - ptr; - arg2 = new char[n+1]; - strncpy(arg2,ptr,n); - arg2[n] = '\0'; - } else arg2 = NULL; - - double value1,value2; + // parentheses: recursively evaluate contents of parens - // customize by adding math function to this list and to if statement - // add(x,y),sub(x,y),mult(x,y),div(x,y),neg(x), - // pow(x,y),exp(x),ln(x),sqrt(x) + else if (onechar == '(') { + if (expect == OP) error->all("Invalid syntax in variable formula"); + expect = OP; + + char *contents; + i = find_matching_paren(str,i,contents); + i++; + + // evaluate contents and push on stack - if (strcmp(func,"add") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); if (tree) { - tree->type = ADD; - tree->left = new Tree(); - tree->right = new Tree(); - value1 = evaluate(arg1,tree->left); - value2 = evaluate(arg2,tree->right); - } else answer = evaluate(arg1,NULL) + evaluate(arg2,NULL); + Tree *newtree; + double tmp = evaluate(contents,&newtree); + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = evaluate(contents,NULL); + + delete [] contents; + + // number: push value onto stack + + } else if (isdigit(onechar) || onechar == '.') { + if (expect == OP) error->all("Invalid syntax in variable formula"); + expect = OP; + + // istop = end of number, including scientific notation + + int istart = i; + int istop = istart + strspn(&str[i],"0123456789eE.-") - 1; + while (str[istop] == '-') istop--; + i = istop + 1; + + int n = istop - istart + 1; + char *number = new char[n+1]; + strncpy(number,&str[istart],n); + number[n] = '\0'; - } else if (strcmp(func,"sub") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); if (tree) { - tree->type = SUB; - tree->left = new Tree(); - tree->right = new Tree(); - value1 = evaluate(arg1,tree->left); - value2 = evaluate(arg2,tree->right); - } else answer = evaluate(arg1,NULL) - evaluate(arg2,NULL); + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = atof(number); + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = atof(number); - } else if (strcmp(func,"mult") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - if (tree) { - tree->type = MULT; - tree->left = new Tree(); - tree->right = new Tree(); - value1 = evaluate(arg1,tree->left); - value2 = evaluate(arg2,tree->right); - } else answer = evaluate(arg1,NULL) * evaluate(arg2,NULL); + delete [] number; - } else if (strcmp(func,"div") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - if (tree) { - tree->type = DIV; - tree->left = new Tree(); - tree->right = new Tree(); - value1 = evaluate(arg1,tree->left); - value2 = evaluate(arg2,tree->right); - } else { - value1 = evaluate(arg1,NULL); - value2 = evaluate(arg2,NULL); - if (value2 == 0.0) error->all("Cannot evaluate variable"); - answer = value1 / value2; - } + // letter: c_ID, f_ID, v_name, exp(), xcm(,), x[234], x[], vol - } else if (strcmp(func,"neg") == 0) { - if (arg2) error->all("Cannot evaluate variable"); - if (tree) { - tree->type = NEG; - tree->left = new Tree(); - value1 = evaluate(arg1,tree->left); - } else answer = -evaluate(arg1,NULL); + } else if (islower(onechar)) { + if (expect == OP) error->all("Invalid syntax in variable formula"); + expect = OP; - } else if (strcmp(func,"pow") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - if (tree) { - tree->type = POW; - tree->left = new Tree(); - tree->right = new Tree(); - value1 = evaluate(arg1,tree->left); - value2 = evaluate(arg2,tree->right); - } else { - value1 = evaluate(arg1,NULL); - value2 = evaluate(arg2,NULL); - if (value2 == 0.0) error->all("Cannot evaluate variable"); - answer = pow(value1,value2); - } + // istop = end of word, assumed to be alphanumeric or underscore - } else if (strcmp(func,"exp") == 0) { - if (arg2) error->all("Cannot evaluate variable"); - if (tree) { - tree->type = EXP; - tree->left = new Tree(); - value1 = evaluate(arg1,tree->left); - } else answer = exp(evaluate(arg1,NULL)); + int istart = i; + while (isalnum(str[i]) || str[i] == '_') i++; + int istop = i-1; - } else if (strcmp(func,"ln") == 0) { - if (arg2) error->all("Cannot evaluate variable"); - if (tree) { - tree->type = LN; - tree->left = new Tree(); - value1 = evaluate(arg1,tree->left); - } else { - value1 = evaluate(arg1,NULL); - if (value1 == 0.0) error->all("Cannot evaluate variable"); - answer = log(value1); - } + int n = istop - istart + 1; + char *word = new char[n+1]; + strncpy(word,&str[istart],n); + word[n] = '\0'; - } else if (strcmp(func,"sqrt") == 0) { - if (arg2) error->all("Cannot evaluate variable"); - if (tree) { - tree->type = SQRT; - tree->left = new Tree(); - value1 = evaluate(arg1,tree->left); - } else { - value1 = evaluate(arg1,NULL); - if (value1 == 0.0) error->all("Cannot evaluate variable"); - answer = sqrt(value1); - } + // compute - // customize by adding group function to this list and to if statement - // mass(group),charge(group),xcm(group,dim),vcm(group,dim), - // fcm(group,dim),bound(group,xmin),gyration(group) + if (strncmp(word,"c_",2) == 0) { + n = strlen(word) - 2 + 1; + char *id = new char[n]; + strcpy(id,&word[2]); - } else if (strcmp(func,"mass") == 0) { - if (arg2) error->all("Cannot evaluate variable"); - int igroup = group->find(arg1); - if (igroup == -1) error->all("Variable group ID does not exist"); - atom->check_mass(); - answer = group->mass(igroup); + if (update->first_update == 0) + error->all("Compute in variable formula before initial run"); - } else if (strcmp(func,"charge") == 0) { - if (arg2) error->all("Cannot evaluate variable"); - int igroup = group->find(arg1); - if (igroup == -1) error->all("Variable group ID does not exist"); - answer = group->charge(igroup); + int icompute; + for (icompute = 0; icompute < modify->ncompute; icompute++) + if (strcmp(id,modify->compute[icompute]->id) == 0) break; + if (icompute == modify->ncompute) + error->all("Invalid compute ID in variable formula"); + Compute *compute = modify->compute[icompute]; - } else if (strcmp(func,"xcm") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - int igroup = group->find(arg1); - if (igroup == -1) error->all("Variable group ID does not exist"); - atom->check_mass(); - double masstotal = group->mass(igroup); - double xcm[3]; - group->xcm(igroup,masstotal,xcm); - if (strcmp(arg2,"x") == 0) answer = xcm[0]; - else if (strcmp(arg2,"y") == 0) answer = xcm[1]; - else if (strcmp(arg2,"z") == 0) answer = xcm[2]; - else error->all("Cannot evaluate variable"); + delete [] id; - } else if (strcmp(func,"vcm") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - int igroup = group->find(arg1); - if (igroup == -1) error->all("Variable group ID does not exist"); - atom->check_mass(); - double masstotal = group->mass(igroup); - double vcm[3]; - group->vcm(igroup,masstotal,vcm); - if (strcmp(arg2,"x") == 0) answer = vcm[0]; - else if (strcmp(arg2,"y") == 0) answer = vcm[1]; - else if (strcmp(arg2,"z") == 0) answer = vcm[2]; - else error->all("Cannot evaluate variable"); + int index = 0; + if (str[i] == '[') { + i = int_between_brackets(str,i,index,0); + i++; + } - } else if (strcmp(func,"fcm") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - int igroup = group->find(arg1); - if (igroup == -1) error->all("Variable group ID does not exist"); - double fcm[3]; - group->fcm(igroup,fcm); - if (strcmp(arg2,"x") == 0) answer = fcm[0]; - else if (strcmp(arg2,"y") == 0) answer = fcm[1]; - else if (strcmp(arg2,"z") == 0) answer = fcm[2]; - else error->all("Cannot evaluate variable"); + // global or per-atom scalar compute - } else if (strcmp(func,"bound") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - int igroup = group->find(arg1); - if (igroup == -1) error->all("Variable group ID does not exist"); - double minmax[6]; - group->bounds(igroup,minmax); - if (strcmp(arg2,"xmin") == 0) answer = minmax[0]; - else if (strcmp(arg2,"xmax") == 0) answer = minmax[1]; - else if (strcmp(arg2,"ymin") == 0) answer = minmax[2]; - else if (strcmp(arg2,"ymax") == 0) answer = minmax[3]; - else if (strcmp(arg2,"zmin") == 0) answer = minmax[4]; - else if (strcmp(arg2,"zmax") == 0) answer = minmax[5]; - else error->all("Cannot evaluate variable"); + if (index == 0) { + if (compute->scalar_flag) { + if (!(compute->invoked & INVOKED_SCALAR)) + value1 = compute->compute_scalar(); + else value1 = compute->scalar; + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value1; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value1; - } else if (strcmp(func,"gyration") == 0) { - if (!arg2) error->all("Cannot evaluate variable"); - int igroup = group->find(arg1); - if (igroup == -1) error->all("Variable group ID does not exist"); - atom->check_mass(); - double masstotal = group->mass(igroup); - double xcm[3]; - group->xcm(igroup,masstotal,xcm); - answer = group->gyration(igroup,masstotal,xcm); + } else if (compute->peratom_flag && compute->size_peratom == 0) { + if (tree == NULL) + error->all("Per-atom compute in equal-style variable formula"); + if (!(compute->invoked & INVOKED_PERATOM)) + compute->compute_peratom(); + Tree *newtree = new Tree(); + newtree->type = ATOMARRAY; + newtree->array = compute->scalar_atom; + newtree->nstride = 1; + treestack[ntreestack++] = newtree; + } else error->all("Mismatched compute in variable formula"); - } else error->all("Invalid math/group function in variable"); + // global or per-atom vector compute - delete [] func; - delete [] arg1; - delete [] arg2; - - // string is a "vector" since contains [] - // index = everything between [] evaluated as integer - // if vector name starts with "c_", trailing chars are compute ID - // check if compute ID exists, invoke it with index as arg - // if vector name starts with "cf_", trailing chars are fix ID - // check if fix ID exists, call its scalar or vector fn with index as arg - // else is atom vector - // find which proc owns atom via atom->map() - // grab atom-based value with index as global atom ID - - } else if (strchr(str,'[')) { - if (str[strlen(str)-1] != ']') error->all("Cannot evaluate variable"); - - char *ptr = strchr(str,'['); - int n = ptr - str; - char *vector = new char[n+1]; - strncpy(vector,str,n); - vector[n] = '\0'; - - char *arg; - ptr++; - char *ptr2 = &str[strlen(str)-1]; - n = ptr2 - ptr; - arg = new char[n+1]; - strncpy(arg,ptr,n); - arg[n] = '\0'; - - if (strncmp(vector,"c_",2) == 0) { - n = strlen(vector) - 2 + 1; - char *id = new char[n]; - strcpy(id,&vector[2]); - - int icompute; - for (icompute = 0; icompute < modify->ncompute; icompute++) - if (strcmp(id,modify->compute[icompute]->id) == 0) break; - if (icompute == modify->ncompute) - error->all("Invalid compute ID in variable"); - delete [] id; - modify->compute[icompute]->init(); - - // call compute_scalar() if index = 0, else compute_vector() - // if defined, first call Compute object's pre-compute(s) - - int index = atoi(arg); - if (index == 0) { - if (modify->compute[icompute]->scalar_flag == 0) - error->all("Variable compute ID does not compute scalar info"); - if (modify->compute[icompute]->npre) - for (int ic = 0; ic < modify->compute[icompute]->npre; ic++) { - int ipre = - modify->find_compute(modify->compute[icompute]->id_pre[ic]); - if (ipre < 0) error->all("Could not pre-compute in variable"); - double tmp = modify->compute[ipre]->compute_scalar(); - } - answer = modify->compute[icompute]->compute_scalar(); - } else if (index > 0) { - if (modify->compute[icompute]->vector_flag == 0) - error->all("Variable compute ID does not compute vector info"); - if (index > modify->compute[icompute]->size_vector) - error->all("Variable compute ID vector is not large enough"); - if (modify->compute[icompute]->npre) - for (int ic = 0; ic < modify->compute[icompute]->npre; ic++) { - int ipre = - modify->find_compute(modify->compute[icompute]->id_pre[ic]); - if (ipre < 0) error->all("Could not pre-compute in variable"); - modify->compute[ipre]->compute_vector(); - } - modify->compute[icompute]->compute_vector(); - answer = modify->compute[icompute]->vector[index-1]; - } else error->all("Invalid compute ID index in variable"); - - } else if (strncmp(vector,"f_",2) == 0) { - n = strlen(vector) - 2 + 1; - char *id = new char[n]; - strcpy(id,&vector[2]); - - int ifix; - for (ifix = 0; ifix < modify->nfix; ifix++) - if (strcmp(id,modify->fix[ifix]->id) == 0) break; - if (ifix == modify->nfix) - error->all("Invalid fix ID in variable"); - delete [] id; - - // call compute_scalar() if index = 0, else compute_vector() - - int index = atoi(arg); - if (index == 0) { - if (modify->fix[ifix]->scalar_flag == 0) - error->all("Variable fix ID does not compute scalar info"); - answer = modify->fix[ifix]->compute_scalar(); - } else if (index > 0) { - if (modify->fix[ifix]->vector_flag == 0) - error->all("Variable fix ID does not compute vector info"); - if (index > modify->fix[ifix]->size_vector) - error->all("Variable fix ID vector is not large enough"); - answer = modify->fix[ifix]->compute_vector(index-1); - } else error->all("Invalid fix ID index in variable"); - - } else if (tree) { - - if (strlen(arg)) error->all("Invalid atom vector in variable"); - - // customize by adding atom vector to this list and to if statement - // mass,x,y,z,vx,vy,vz,fx,fy,fz - - tree->type = ATOMARRAY; - tree->nstride = 3; - - if (strcmp(vector,"mass") == 0) { - if (atom->mass) { - tree->type = TYPEARRAY; - tree->array = atom->mass; } else { - tree->nstride = 1; - tree->array = atom->rmass; + if (compute->vector_flag) { + if (index > compute->size_vector) + error->all("Compute vector in variable formula is too small"); + if (!(compute->invoked & INVOKED_VECTOR)) compute->compute_vector(); + value1 = compute->vector[index-1]; + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value1; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value1; + + } else if (compute->peratom_flag && compute->size_peratom) { + if (tree == NULL) + error->all("Per-atom compute in equal-style variable formula"); + if (index > compute->size_peratom) + error->all("Compute vector in variable formula is too small"); + if (!(compute->invoked & INVOKED_PERATOM)) + compute->compute_peratom(); + Tree *newtree = new Tree(); + newtree->type = ATOMARRAY; + newtree->array = &compute->vector_atom[0][index-1]; + newtree->nstride = compute->size_peratom; + treestack[ntreestack++] = newtree; + } else error->all("Mismatched compute in variable formula"); + } + + // fix + + } else if (strncmp(word,"f_",2) == 0) { + n = strlen(word) - 2 + 1; + char *id = new char[n]; + strcpy(id,&word[2]); + + if (update->first_update == 0) + error->all("Fix in variable formula before initial run"); + + int ifix; + for (ifix = 0; ifix < modify->nfix; ifix++) + if (strcmp(id,modify->fix[ifix]->id) == 0) break; + if (ifix == modify->nfix) + error->all("Invalid fix ID in variable formula"); + Fix *fix = modify->fix[ifix]; + + delete [] id; + + int index = 0; + if (str[i] == '[') { + i = int_between_brackets(str,i,index,0); + i++; + } + + // global or per-atom scalar fix + + if (index == 0) { + if (fix->scalar_flag) { + if (update->ntimestep % fix->scalar_vector_freq) + error->all("Fix in variable not computed at compatible time"); + value1 = fix->compute_scalar(); + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value1; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value1; + + } else if (fix->peratom_flag && fix->size_peratom == 0) { + if (tree == NULL) + error->all("Per-atom fix in equal-style variable formula"); + if (update->ntimestep % fix->peratom_freq) + error->all("Fix in variable not computed at compatible time"); + Tree *newtree = new Tree(); + newtree->type = ATOMARRAY; + newtree->array = fix->scalar_atom; + newtree->nstride = 1; + treestack[ntreestack++] = newtree; + } else error->all("Mismatched fix in variable formula"); + + // global or per-atom vector fix + + } else { + if (fix->vector_flag) { + if (index > fix->size_vector) + error->all("Fix vector in variable formula is too small"); + value1 = fix->compute_vector(index-1); + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value1; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value1; + + } else if (fix->peratom_flag && fix->size_peratom) { + if (tree == NULL) + error->all("Per-atom fix in equal-style variable formula"); + if (index > fix->size_peratom) + error->all("Fix vector in variable formula is too small"); + if (update->ntimestep % fix->peratom_freq) + error->all("Fix in variable not computed at compatible time"); + Tree *newtree = new Tree(); + newtree->type = ATOMARRAY; + newtree->array = &fix->vector_atom[0][index-1]; + newtree->nstride = fix->size_peratom; + treestack[ntreestack++] = newtree; + } else error->all("Mismatched fix in variable formula"); + } + + // variable + + } else if (strncmp(word,"v_",2) == 0) { + n = strlen(word) - 2 + 1; + char *id = new char[n]; + strcpy(id,&word[2]); + + int ivar = find(id); + if (ivar == -1) error->all("Invalid variable name in variable formula"); + char *var = retrieve(id); + if (var == NULL && style[ivar] != ATOM) + error->all("Invalid variable evaluation in variable formula"); + + if (tree) { + Tree *newtree; + if (style[ivar] != ATOM) { + newtree = new Tree(); + newtree->type = VALUE; + newtree->value = atof(var); + } else double tmp = evaluate(data[ivar][0],&newtree); + treestack[ntreestack++] = newtree; + + } else { + if (style[ivar] == ATOM) + error->all("Atom-style variable in equal-style variable formula"); + argstack[nargstack++] = atof(var); + } + + delete [] id; + + // math/group function or atom value/vector or thermo keyword + + } else { + + // math or group function + + if (str[i] == '(') { + char *contents; + i = find_matching_paren(str,i,contents); + i++; + + if (math_function(word,contents,tree, + treestack,ntreestack,argstack,nargstack)); + else if (group_function(word,contents,tree, + treestack,ntreestack,argstack,nargstack)); + else error->all("Invalid math or group function in variable formula"); + + delete [] contents; + + // atom value or vector + + } else if (str[i] == '[') { + int id; + i = int_between_brackets(str,i,id,1); + i++; + + // ID between brackets exists, atom value + // empty brackets, atom vector + + if (id > 0) + atom_value(word,id,tree,treestack,ntreestack,argstack,nargstack); + else + atom_vector(word,tree,treestack,ntreestack); + + // thermo keyword + + } else { + if (update->first_update == 0) + error->all("Thermo keyword in variable formula before initial run"); + int flag = output->thermo->evaluate_keyword(word,&value1); + if (flag) error->all("Invalid thermo keyword in variable formula"); + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value1; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value1; } } - else if (strcmp(vector,"x") == 0) tree->array = &atom->x[0][0]; - else if (strcmp(vector,"y") == 0) tree->array = &atom->x[0][1]; - else if (strcmp(vector,"z") == 0) tree->array = &atom->x[0][2]; - else if (strcmp(vector,"vx") == 0) tree->array = &atom->v[0][0]; - else if (strcmp(vector,"vy") == 0) tree->array = &atom->v[0][1]; - else if (strcmp(vector,"vz") == 0) tree->array = &atom->v[0][2]; - else if (strcmp(vector,"fx") == 0) tree->array = &atom->f[0][0]; - else if (strcmp(vector,"fy") == 0) tree->array = &atom->f[0][1]; - else if (strcmp(vector,"fz") == 0) tree->array = &atom->f[0][2]; - - else error->all("Invalid atom vector in variable"); - } else { + delete [] word; - if (atom->map_style == 0) - error->all("Cannot use atom vector in variable unless atom map exists"); + // math operator, including end-of-string - int index = atom->map(atoi(arg)); + } else if (strchr("+-*/^\0",onechar)) { + if (onechar == '+') op = ADD; + else if (onechar == '-') op = SUBTRACT; + else if (onechar == '*') op = MULTIPLY; + else if (onechar == '/') op = DIVIDE; + else if (onechar == '^') op = CARAT; + else op = DONE; + i++; - // customize by adding atom vector to this list and to if statement - // mass,x,y,z,vx,vy,vz,fx,fy,fz + if (op == SUBTRACT && expect == ARG) { + opstack[nopstack++] = UNARY; + continue; + } - double mine; - if (index >= 0 && index < atom->nlocal) { + if (expect == ARG) error->all("Invalid syntax in variable formula"); + expect = ARG; - if (strcmp(vector,"mass") == 0) { - if (atom->mass) mine = atom->mass[atom->type[index]]; - else mine = atom->rmass[index]; + // evaluate stack as deep as possible while respecting precedence + // before pushing current op onto stack + + while (nopstack && precedence[opstack[nopstack-1]] >= precedence[op]) { + opprevious = opstack[--nopstack]; + + if (tree) { + Tree *newtree = new Tree(); + newtree->type = opprevious; + newtree->right = treestack[--ntreestack]; + if (opprevious == UNARY) newtree->left = newtree->right; + else newtree->left = treestack[--ntreestack]; + treestack[ntreestack++] = newtree; + + } else { + value2 = argstack[--nargstack]; + if (opprevious != UNARY) value1 = argstack[--nargstack]; + + if (opprevious == ADD) + argstack[nargstack++] = value1 + value2; + else if (opprevious == SUBTRACT) + argstack[nargstack++] = value1 - value2; + else if (opprevious == MULTIPLY) + argstack[nargstack++] = value1 * value2; + else if (opprevious == DIVIDE) { + if (value2 == 0.0) error->all("Divide by 0 in variable formula"); + argstack[nargstack++] = value1 / value2; + } else if (opprevious == CARAT) { + if (value2 == 0.0) error->all("Power by 0 in variable formula"); + argstack[nargstack++] = pow(value1,value2); + } else if (opprevious == UNARY) + argstack[nargstack++] = -value2; } - else if (strcmp(vector,"x") == 0) mine = atom->x[index][0]; - else if (strcmp(vector,"y") == 0) mine = atom->x[index][1]; - else if (strcmp(vector,"z") == 0) mine = atom->x[index][2]; - else if (strcmp(vector,"vx") == 0) mine = atom->v[index][0]; - else if (strcmp(vector,"vy") == 0) mine = atom->v[index][1]; - else if (strcmp(vector,"vz") == 0) mine = atom->v[index][2]; - else if (strcmp(vector,"fx") == 0) mine = atom->f[index][0]; - else if (strcmp(vector,"fy") == 0) mine = atom->f[index][1]; - else if (strcmp(vector,"fz") == 0) mine = atom->f[index][2]; - - else error->one("Invalid atom vector in variable"); - - } else mine = 0.0; + } - MPI_Allreduce(&mine,&answer,1,MPI_DOUBLE,MPI_SUM,world); - } + // if end-of-string, break out of entire formula evaluation loop - delete [] vector; - delete [] arg; + if (op == DONE) break; - // string is "keyword" since starts with lowercase letter - // if keyword starts with "v_", trailing chars are variable name - // evaluate it via retrieve(), convert it to double - // else is thermo keyword - // evaluate it via evaluate_keyword() + // push current operation onto stack - } else if (islower(str[0])) { + opstack[nopstack++] = op; - if (strncmp(str,"v_",2) == 0) { - int n = strlen(str) - 2 + 1; - char *id = new char[n]; - strcpy(id,&str[2]); - - char *v = retrieve(id); - if (v == NULL) error->all("Invalid variable name in variable"); - delete [] id; - - answer = atof(v); - - } else { - int flag = output->thermo->evaluate_keyword(str,&answer); - if (flag) error->all("Invalid thermo keyword in variable"); - } - - // string is a number since starts with digit or "." or "-" - // just copy to result - - } else if (isdigit(str[0]) || str[0] == '.' || str[0] == '-') { - - answer = atof(str); - - // string is an error - - } else error->all("Cannot evaluate variable"); - - // store answer in tree and return it - - if (tree) tree->value = answer; - return answer; -} - -/* ---------------------------------------------------------------------- */ - -void Variable::build_parse_tree(int ivar) -{ - if (style[ivar] != ATOM) - error->all("Cannot build parse tree for variable that is not atom style"); - ptree = new Tree(); - double tmp = evaluate(data[ivar][0],ptree); -} - -/* ---------------------------------------------------------------------- */ - -void Variable::evaluate_parse_tree(int igroup, double *result) -{ - int groupbit = group->bitmask[igroup]; - int *mask = atom->mask; - int nlocal = atom->nlocal; - - for (int i = 0; i < nlocal; i++) { - if (mask[i] && groupbit) result[i] = eval_tree(ptree,i); - else result[i] = 0.0; + } else error->all("Invalid syntax in variable formula"); } -} -/* ---------------------------------------------------------------------- */ + if (nopstack) error->all("Invalid syntax in variable formula"); -void Variable::free_parse_tree() -{ - free_tree(ptree); + // for atom-style variable, return remaining tree + // for equal-style variable, return remaining arg + + if (tree) { + if (ntreestack != 1) error->all("Invalid syntax in variable formula"); + *tree = treestack[0]; + return 0.0; + } else { + if (nargstack != 1) error->all("Invalid syntax in variable formula"); + return argstack[0]; + } } /* ---------------------------------------------------------------------- */ @@ -922,22 +928,34 @@ double Variable::eval_tree(Tree *tree, int i) if (tree->type == ADD) return eval_tree(tree->left,i) + eval_tree(tree->right,i); - if (tree->type == SUB) + if (tree->type == SUBTRACT) return eval_tree(tree->left,i) - eval_tree(tree->right,i); - if (tree->type == MULT) + if (tree->type == MULTIPLY) return eval_tree(tree->left,i) * eval_tree(tree->right,i); - if (tree->type == DIV) - return eval_tree(tree->left,i) / eval_tree(tree->right,i); - if (tree->type == NEG) + if (tree->type == DIVIDE) { + double denom = eval_tree(tree->right,i); + if (denom == 0.0) error->all("Divide by 0 in variable formula"); + return eval_tree(tree->left,i) / denom; + } + if (tree->type == CARAT) { + double exponent = eval_tree(tree->right,i); + if (exponent == 0.0) error->all("Power by 0 in variable formula"); + return pow(eval_tree(tree->left,i),exponent); + } + if (tree->type == UNARY) return -eval_tree(tree->left,i); - if (tree->type == POW) - return pow(eval_tree(tree->left,i),eval_tree(tree->right,i)); + if (tree->type == SQRT) { + double arg = eval_tree(tree->left,i); + if (arg < 0.0) error->all("Sqrt of negative in variable formula"); + return sqrt(arg); + } if (tree->type == EXP) return exp(eval_tree(tree->left,i)); - if (tree->type == LN) - return log(eval_tree(tree->left,i)); - if (tree->type == SQRT) - return sqrt(eval_tree(tree->left,i)); + if (tree->type == LN) { + double arg = eval_tree(tree->left,i); + if (arg <= 0.0) error->all("Log of negative/zero in variable formula"); + return log(arg); + } return 0.0; } @@ -950,3 +968,333 @@ void Variable::free_tree(Tree *tree) if (tree->right) free_tree(tree->right); delete tree; } + +/* ---------------------------------------------------------------------- + find matching parenthesis in str, allocate contents = str between parens + i = left paren + return loc or right paren +------------------------------------------------------------------------- */ + +int Variable::find_matching_paren(char *str, int i,char *&contents) +{ + // istop = matching ')' at same level, allowing for nested parens + + int istart = i; + int ilevel = 0; + while (1) { + i++; + if (!str[i]) break; + if (str[i] == '(') ilevel++; + else if (str[i] == ')' && ilevel) ilevel--; + else if (str[i] == ')') break; + } + if (!str[i]) error->all("Invalid syntax in variable formula"); + int istop = i; + + int n = istop - istart - 1; + contents = new char[n+1]; + strncpy(contents,&str[istart+1],n); + contents[n] = '\0'; + + return istop; +} + +/* ---------------------------------------------------------------------- + find int between brackets and set index to its value + if emptyflag and brackets empty, set index to 0 + else if brackets empty, is an error + else contents of brackets must be positive int + i = left bracket + return loc of right bracket +------------------------------------------------------------------------- */ + +int Variable::int_between_brackets(char *str, int i, int &index, int emptyflag) +{ + // istop = matching ']' + + int istart = i; + while (!str[i] || str[i] != ']') i++; + if (!str[i]) error->all("Invalid syntax in variable formula"); + int istop = i; + + int n = istop - istart - 1; + char *arg = new char[n+1]; + strncpy(arg,&str[istart+1],n); + arg[n] = '\0'; + + if (n == 0 && emptyflag) index = 0; + else if (n == 0) error->all("Empty brackets in variable formula"); + else { + index = atoi(arg); + if (index <= 0) error->all("Invalid index in variable formula"); + } + delete [] arg; + + return istop; +} + +/* ---------------------------------------------------------------------- + process a math function in formula + push result onto tree or arg stack + word = math function + contents = str bewteen parentheses + return 0 if not a match, 1 if successfully processed + customize by adding a math function: sqrt(),exp(),log() +------------------------------------------------------------------------- */ + +int Variable::math_function(char *word, char *contents, Tree **tree, + Tree **treestack, int &ntreestack, + double *argstack, int &nargstack) +{ + // word not a match to any math function + + if (strcmp(word,"sqrt") && strcmp(word,"exp") && strcmp(word,"ln")) + return 0; + + Tree *newtree; + double value; + + if (tree) { + newtree = new Tree(); + Tree *argtree; + double tmp = evaluate(contents,&argtree); + newtree->left = argtree; + treestack[ntreestack++] = newtree; + } else value = evaluate(contents,NULL); + + if (strcmp(word,"sqrt") == 0) { + if (tree) newtree->type = SQRT; + else { + if (value < 0.0) error->all("Sqrt of negative in variable formula"); + argstack[nargstack++] = sqrt(value); + } + + } else if (strcmp(word,"exp") == 0) { + if (tree) newtree->type = EXP; + else argstack[nargstack++] = exp(value); + + } else if (strcmp(word,"ln") == 0) { + if (tree) newtree->type = LN; + else { + if (value <= 0.0) error->all("Log of zero/negative in variable formula"); + argstack[nargstack++] = log(value); + } + } + + return 1; +} + + +/* ---------------------------------------------------------------------- + process a group function in formula + push result onto tree or arg stack + word = group function + contents = str bewteen parentheses with one or two args + return 0 if not a match, 1 if successfully processed + customize by adding a group function: + count(group),mass(group),charge(group), + xcm(group,dim),vcm(group,dim),fcm(group,dim), + bound(group,xmin),gyration(group) +------------------------------------------------------------------------- */ + +int Variable::group_function(char *word, char *contents, Tree **tree, + Tree **treestack, int &ntreestack, + double *argstack, int &nargstack) +{ + // parse contents for arg1,arg2 separated by comma + + char *arg1,*arg2; + char *ptr = strchr(contents,','); + if (ptr) *ptr = '\0'; + int n = strlen(contents) + 1; + arg1 = new char[n]; + strcpy(arg1,contents); + if (ptr) { + n = strlen(ptr+1) + 1; + arg2 = new char[n]; + strcpy(arg2,ptr+1); + } else arg2 = NULL; + + int igroup = group->find(arg1); + if (igroup == -1) + error->all("Group ID in variable formula does not exist"); + + Tree *newtree; + double value; + + if (tree) { + newtree = new Tree(); + newtree->type = VALUE; + treestack[ntreestack++] = newtree; + } + + // match word to group function + + if (strcmp(word,"count") == 0) { + if (arg2) + error->all("Invalid group function in variable formula"); + value = group->count(igroup); + + } else if (strcmp(word,"mass") == 0) { + if (arg2) + error->all("Invalid group function in variable formula"); + value = group->mass(igroup); + + } else if (strcmp(word,"charge") == 0) { + if (arg2) + error->all("Invalid group function in variable formula"); + value = group->charge(igroup); + + } else if (strcmp(word,"xcm") == 0) { + if (!arg2) + error->all("Invalid group function in variable formula"); + atom->check_mass(); + double masstotal = group->mass(igroup); + double xcm[3]; + group->xcm(igroup,masstotal,xcm); + if (strcmp(arg2,"x") == 0) value = xcm[0]; + else if (strcmp(arg2,"y") == 0) value = xcm[1]; + else if (strcmp(arg2,"z") == 0) value = xcm[2]; + else error->all("Invalid group function in variable formula"); + + } else if (strcmp(word,"vcm") == 0) { + if (!arg2) + error->all("Invalid group function in variable formula"); + atom->check_mass(); + double masstotal = group->mass(igroup); + double vcm[3]; + group->vcm(igroup,masstotal,vcm); + if (strcmp(arg2,"x") == 0) value = vcm[0]; + else if (strcmp(arg2,"y") == 0) value = vcm[1]; + else if (strcmp(arg2,"z") == 0) value = vcm[2]; + else error->all("Invalid group function in variable formula"); + + } else if (strcmp(word,"fcm") == 0) { + if (!arg2) + error->all("Invalid group function in variable formula"); + double fcm[3]; + group->fcm(igroup,fcm); + if (strcmp(arg2,"x") == 0) value = fcm[0]; + else if (strcmp(arg2,"y") == 0) value = fcm[1]; + else if (strcmp(arg2,"z") == 0) value = fcm[2]; + else error->all("Invalid group function in variable formula"); + + } else if (strcmp(word,"bound") == 0) { + if (!arg2) + error->all("Invalid group function in variable formula"); + double minmax[6]; + group->bounds(igroup,minmax); + if (strcmp(arg2,"xmin") == 0) value = minmax[0]; + else if (strcmp(arg2,"xmax") == 0) value = minmax[1]; + else if (strcmp(arg2,"ymin") == 0) value = minmax[2]; + else if (strcmp(arg2,"ymax") == 0) value = minmax[3]; + else if (strcmp(arg2,"zmin") == 0) value = minmax[4]; + else if (strcmp(arg2,"zmax") == 0) value = minmax[5]; + else error->all("Invalid group function in variable formula"); + + } else if (strcmp(word,"gyration") == 0) { + atom->check_mass(); + double masstotal = group->mass(igroup); + double xcm[3]; + group->xcm(igroup,masstotal,xcm); + value = group->gyration(igroup,masstotal,xcm); + + } else return 0; + + delete [] arg1; + delete [] arg2; + + if (tree) newtree->value= value; + else argstack[nargstack++] = value; + + return 1; +} + +/* ---------------------------------------------------------------------- + process an atom value in formula + push result onto tree or arg stack + word = atom vector + index = positive global ID of atom + customize by adding an atom vector: mass,x,y,z,vx,vy,vz,fx,fy,fz +------------------------------------------------------------------------- */ + +void Variable::atom_value(char *word, int id, Tree **tree, + Tree **treestack, int &ntreestack, + double *argstack, int &nargstack) +{ + if (atom->map_style == 0) + error->all("Atom value in variable formula without atom map"); + + int index = atom->map(id); + + double mine; + if (index >= 0 && index < atom->nlocal) { + + if (strcmp(word,"mass") == 0) { + if (atom->mass) mine = atom->mass[atom->type[index]]; + else mine = atom->rmass[index]; + } + else if (strcmp(word,"x") == 0) mine = atom->x[index][0]; + else if (strcmp(word,"y") == 0) mine = atom->x[index][1]; + else if (strcmp(word,"z") == 0) mine = atom->x[index][2]; + else if (strcmp(word,"vx") == 0) mine = atom->v[index][0]; + else if (strcmp(word,"vy") == 0) mine = atom->v[index][1]; + else if (strcmp(word,"vz") == 0) mine = atom->v[index][2]; + else if (strcmp(word,"fx") == 0) mine = atom->f[index][0]; + else if (strcmp(word,"fy") == 0) mine = atom->f[index][1]; + else if (strcmp(word,"fz") == 0) mine = atom->f[index][2]; + + else error->one("Invalid atom vector in variable formula"); + + } else mine = 0.0; + + double value; + MPI_Allreduce(&mine,&value,1,MPI_DOUBLE,MPI_SUM,world); + + if (tree) { + Tree *newtree = new Tree(); + newtree->type = VALUE; + newtree->value = value; + treestack[ntreestack++] = newtree; + } else argstack[nargstack++] = value; +} + +/* ---------------------------------------------------------------------- + process an atom vector in formula + push result onto tree + word = atom vector + customize by adding an atom vector: mass,x,y,z,vx,vy,vz,fx,fy,fz +------------------------------------------------------------------------- */ + +void Variable::atom_vector(char *word, Tree **tree, + Tree **treestack, int &ntreestack) +{ + if (tree == NULL) + error->all("Atom vector in equal-style variable formula"); + + Tree *newtree = new Tree(); + newtree->type = ATOMARRAY; + newtree->nstride = 3; + treestack[ntreestack++] = newtree; + + if (strcmp(word,"mass") == 0) { + if (atom->mass) { + newtree->type = TYPEARRAY; + newtree->array = atom->mass; + } else { + newtree->nstride = 1; + newtree->array = atom->rmass; + } + } + else if (strcmp(word,"x") == 0) newtree->array = &atom->x[0][0]; + else if (strcmp(word,"y") == 0) newtree->array = &atom->x[0][1]; + else if (strcmp(word,"z") == 0) newtree->array = &atom->x[0][2]; + else if (strcmp(word,"vx") == 0) newtree->array = &atom->v[0][0]; + else if (strcmp(word,"vy") == 0) newtree->array = &atom->v[0][1]; + else if (strcmp(word,"vz") == 0) newtree->array = &atom->v[0][2]; + else if (strcmp(word,"fx") == 0) newtree->array = &atom->f[0][0]; + else if (strcmp(word,"fy") == 0) newtree->array = &atom->f[0][1]; + else if (strcmp(word,"fz") == 0) newtree->array = &atom->f[0][2]; + + else error->all("Invalid atom vector in variable formula"); +} diff --git a/src/variable.h b/src/variable.h index a8a2d7dddb..332d0879ad 100644 --- a/src/variable.h +++ b/src/variable.h @@ -26,12 +26,11 @@ class Variable : protected Pointers { void set(char *, char *); int next(int, char **); int find(char *); - int peratom(int); + int equalstyle(int); + int atomstyle(int); char *retrieve(char *); - - void build_parse_tree(int); - void evaluate_parse_tree(int, double *); - void free_parse_tree(); + double compute_equal(int); + void compute_atom(int, int, double *, int, int); private: int me; @@ -42,8 +41,9 @@ class Variable : protected Pointers { int *num; // # of values for each variable int *index; // next available value for each variable char ***data; // str value of each variable's values + int precedence[7]; // precedence level of math operators - struct Tree { + struct Tree { // parse tree for atom-style variables double value; double *array; int nstride; @@ -51,13 +51,17 @@ class Variable : protected Pointers { Tree *left,*right; }; - Tree *ptree; // parse tree for an ATOM variable - void copy(int, char **, char **); - double evaluate(char *, Tree *); + double evaluate(char *, Tree **); void remove(int); double eval_tree(Tree *, int); void free_tree(Tree *); + int find_matching_paren(char *, int, char *&); + int int_between_brackets(char *, int, int &, int); + int math_function(char *, char *, Tree **, Tree **, int &, double *, int &); + int group_function(char *, char *, Tree **, Tree **, int &, double *, int &); + void atom_value(char *, int, Tree **, Tree **, int &, double *, int &); + void atom_vector(char *, Tree **, Tree **, int &); }; }