Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F71156537
fix_cmap.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Jul 10, 00:03
Size
45 KB
Mime Type
text/x-c
Expires
Fri, Jul 12, 00:03 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
18914896
Attached To
rLAMMPS lammps
fix_cmap.cpp
View Options
/* ----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors:
Xiaohu Hu, CMB/ORNL (hux2@ornl.gov)
David Hyde-Volpe, Tigran Abramyan, and Robert A. Latour (Clemson University)
Chris Lorenz (Kings College-London)
Implementation of the CHARMM CMAP; adds an extra energy term for the
peptide backbone dihedrals. The tools/ch2lmp/charmm2lammps.pl
conversion script, which generates an extra section in the LAMMPS data
file, is needed in order to generate the info used by this fix style.
References:
- MacKerell et al., J. Am. Chem. Soc. 126(2004):698-699.
- MacKerell et al., J. Comput. Chem. 25(2004):1400-1415.
------------------------------------------------------------------------- */
#include <mpi.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "fix_cmap.h"
#include "atom.h"
#include "atom_vec.h"
#include "update.h"
#include "respa.h"
#include "modify.h"
#include "domain.h"
#include "force.h"
#include "group.h"
#include "comm.h"
#include "math_const.h"
#include "memory.h"
#include "error.h"
using namespace LAMMPS_NS;
using namespace FixConst;
using namespace MathConst;
#define MAXLINE 256
#define LISTDELTA 10000
#define LB_FACTOR 1.5
#define CMAPMAX 6 // max # of CMAP terms stored by one atom
#define CMAPDIM 24 // grid map dimension is 24 x 24
#define CMAPXMIN -360.0
#define CMAPXMIN2 -180.0
#define CMAPDX 15.0 // 360/CMAPDIM
/* ---------------------------------------------------------------------- */
FixCMAP::FixCMAP(LAMMPS *lmp, int narg, char **arg) :
Fix(lmp, narg, arg),
crosstermlist(NULL), num_crossterm(NULL), crossterm_type(NULL),
crossterm_atom1(NULL), crossterm_atom2(NULL), crossterm_atom3(NULL),
crossterm_atom4(NULL), crossterm_atom5(NULL),
g_axis(NULL), cmapgrid(NULL), d1cmapgrid(NULL), d2cmapgrid(NULL),
d12cmapgrid(NULL)
{
if (narg != 4) error->all(FLERR,"Illegal fix cmap command");
restart_global = 1;
restart_peratom = 1;
peatom_flag = 1;
virial_flag = 1;
peratom_freq = 1;
scalar_flag = 1;
global_freq = 1;
extscalar = 1;
extvector = 1;
wd_header = 1;
wd_section = 1;
MPI_Comm_rank(world,&me);
MPI_Comm_size(world,&nprocs);
// allocate memory for CMAP data
memory->create(g_axis,CMAPDIM,"cmap:g_axis");
memory->create(cmapgrid,6,CMAPDIM,CMAPDIM,"cmap:grid");
memory->create(d1cmapgrid,6,CMAPDIM,CMAPDIM,"cmap:d1grid");
memory->create(d2cmapgrid,6,CMAPDIM,CMAPDIM,"cmap:d2grid");
memory->create(d12cmapgrid,6,CMAPDIM,CMAPDIM,"cmap:d12grid");
// read and setup CMAP data
read_grid_map(arg[3]);
// perform initial allocation of atom-based arrays
// register with Atom class
num_crossterm = NULL;
crossterm_type = NULL;
crossterm_atom1 = NULL;
crossterm_atom2 = NULL;
crossterm_atom3 = NULL;
crossterm_atom4 = NULL;
crossterm_atom5 = NULL;
nmax_previous = 0;
grow_arrays(atom->nmax);
atom->add_callback(0);
atom->add_callback(1);
// local list of crossterms
ncmap = 0;
maxcrossterm = 0;
crosstermlist = NULL;
}
/* --------------------------------------------------------------------- */
FixCMAP::~FixCMAP()
{
// unregister callbacks to this fix from Atom class
atom->delete_callback(id,0);
atom->delete_callback(id,1);
memory->destroy(g_axis);
memory->destroy(cmapgrid);
memory->destroy(d1cmapgrid);
memory->destroy(d2cmapgrid);
memory->destroy(d12cmapgrid);
memory->destroy(crosstermlist);
memory->destroy(num_crossterm);
memory->destroy(crossterm_type);
memory->destroy(crossterm_atom1);
memory->destroy(crossterm_atom2);
memory->destroy(crossterm_atom3);
memory->destroy(crossterm_atom4);
memory->destroy(crossterm_atom5);
}
/* ---------------------------------------------------------------------- */
int FixCMAP::setmask()
{
int mask = 0;
mask |= PRE_NEIGHBOR;
mask |= PRE_REVERSE;
mask |= POST_FORCE;
mask |= THERMO_ENERGY;
mask |= POST_FORCE_RESPA;
mask |= MIN_POST_FORCE;
return mask;
}
/* ---------------------------------------------------------------------- */
void FixCMAP::init()
{
int i;
double angle;
i = 0;
angle = -180.0;
while (angle < 180.0) {
g_axis[i] = angle;
angle += CMAPDX;
i++;
}
// pre-compute the derivatives of the maps
for (i = 0; i < 6; i++)
set_map_derivatives(cmapgrid[i],d1cmapgrid[i],d2cmapgrid[i],d12cmapgrid[i]);
// define newton_bond here in case restart file was read (not data file)
newton_bond = force->newton_bond;
}
/* --------------------------------------------------------------------- */
void FixCMAP::setup(int vflag)
{
pre_neighbor();
if (strstr(update->integrate_style,"verlet"))
post_force(vflag);
else {
((Respa *) update->integrate)->copy_flevel_f(nlevels_respa-1);
post_force_respa(vflag,nlevels_respa-1,0);
((Respa *) update->integrate)->copy_f_flevel(nlevels_respa-1);
}
}
/* --------------------------------------------------------------------- */
void FixCMAP::setup_pre_neighbor()
{
pre_neighbor();
}
/* --------------------------------------------------------------------- */
void FixCMAP::setup_pre_reverse(int eflag, int vflag)
{
pre_reverse(eflag,vflag);
}
/* --------------------------------------------------------------------- */
void FixCMAP::min_setup(int vflag)
{
pre_neighbor();
post_force(vflag);
}
/* ----------------------------------------------------------------------
store local neighbor list as if newton_bond = OFF, even if actually ON
------------------------------------------------------------------------- */
void FixCMAP::pre_neighbor()
{
int i,m,atom1,atom2,atom3,atom4,atom5;
// guesstimate initial length of local crossterm list
// if ncmap was not set (due to read_restart, no read_data),
// then list will grow by LISTDELTA chunks
if (maxcrossterm == 0) {
if (nprocs == 1) maxcrossterm = ncmap;
else maxcrossterm = static_cast<int> (LB_FACTOR*ncmap/nprocs);
memory->create(crosstermlist,maxcrossterm,6,"cmap:crosstermlist");
}
int nlocal = atom->nlocal;
ncrosstermlist = 0;
for (i = 0; i < nlocal; i++) {
for (m = 0; m < num_crossterm[i]; m++) {
atom1 = atom->map(crossterm_atom1[i][m]);
atom2 = atom->map(crossterm_atom2[i][m]);
atom3 = atom->map(crossterm_atom3[i][m]);
atom4 = atom->map(crossterm_atom4[i][m]);
atom5 = atom->map(crossterm_atom5[i][m]);
if (atom1 == -1 || atom2 == -1 || atom3 == -1 ||
atom4 == -1 || atom5 == -1) {
char str[128];
sprintf(str,"CMAP atoms "
TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT " "
TAGINT_FORMAT " " TAGINT_FORMAT
" missing on proc %d at step " BIGINT_FORMAT,
crossterm_atom1[i][m],crossterm_atom2[i][m],
crossterm_atom3[i][m],crossterm_atom4[i][m],
crossterm_atom5[i][m],me,update->ntimestep);
error->one(FLERR,str);
}
atom1 = domain->closest_image(i,atom1);
atom2 = domain->closest_image(i,atom2);
atom3 = domain->closest_image(i,atom3);
atom4 = domain->closest_image(i,atom4);
atom5 = domain->closest_image(i,atom5);
if (i <= atom1 && i <= atom2 && i <= atom3 &&
i <= atom4 && i <= atom5) {
if (ncrosstermlist == maxcrossterm) {
maxcrossterm += LISTDELTA;
memory->grow(crosstermlist,maxcrossterm,6,"cmap:crosstermlist");
}
crosstermlist[ncrosstermlist][0] = atom1;
crosstermlist[ncrosstermlist][1] = atom2;
crosstermlist[ncrosstermlist][2] = atom3;
crosstermlist[ncrosstermlist][3] = atom4;
crosstermlist[ncrosstermlist][4] = atom5;
crosstermlist[ncrosstermlist][5] = crossterm_type[i][m];
ncrosstermlist++;
}
}
}
}
/* ----------------------------------------------------------------------
store eflag, so can use it in post_force to tally per-atom energies
------------------------------------------------------------------------- */
void FixCMAP::pre_reverse(int eflag, int vflag)
{
eflag_caller = eflag;
}
/* ----------------------------------------------------------------------
compute CMAP terms as if newton_bond = OFF, even if actually ON
------------------------------------------------------------------------- */
void FixCMAP::post_force(int vflag)
{
int n,i1,i2,i3,i4,i5,type,nlist;
int li1, li2, mli1,mli2,mli11,mli21,t1,li3,li4,mli3,mli4,mli31,mli41;
int list[5];
// vectors needed to calculate the cross-term dihedral angles
double vb21x,vb21y,vb21z,vb32x,vb32y,vb32z,vb34x,vb34y,vb34z;
double vb23x,vb23y,vb23z;
double vb43x,vb43y,vb43z,vb45x,vb45y,vb45z,a1x,a1y,a1z,b1x,b1y,b1z;
double a2x,a2y,a2z,b2x,b2y,b2z,r32,a1sq,b1sq,a2sq,b2sq,dpr21r32,dpr34r32;
double dpr32r43,dpr45r43,r43,vb12x,vb12y,vb12z,vb54x,vb54y,vb54z;
// cross-term dihedral angles
double phi,psi,phi1,psi1;
double f1[3],f2[3],f3[3],f4[3],f5[3],vcmap[6];
double gs[4],d1gs[4],d2gs[4],d12gs[4];
double engfraction;
// vectors needed for the gradient/force calculation
double dphidr1x,dphidr1y,dphidr1z,dphidr2x,dphidr2y,dphidr2z;
double dphidr3x,dphidr3y,dphidr3z,dphidr4x,dphidr4y,dphidr4z;
double dpsidr1x,dpsidr1y,dpsidr1z,dpsidr2x,dpsidr2y,dpsidr2z;
double dpsidr3x,dpsidr3y,dpsidr3z,dpsidr4x,dpsidr4y,dpsidr4z;
// Definition of cross-term dihedrals
// phi dihedral
// |--------------------|
// a1-----a2-----a3-----a4-----a5 cross-term atoms
// C N CA C N cross-term atom types
// |--------------------|
// psi dihedral
double **x = atom->x;
double **f = atom->f;
int nlocal = atom->nlocal;
ecmap = 0.0;
int eflag = eflag_caller;
if (eflag || vflag) ev_setup(eflag,vflag);
else evflag = 0;
for (n = 0; n < ncrosstermlist; n++) {
i1 = crosstermlist[n][0];
i2 = crosstermlist[n][1];
i3 = crosstermlist[n][2];
i4 = crosstermlist[n][3];
i5 = crosstermlist[n][4];
type = crosstermlist[n][5];
if (type == 0) continue;
// calculate bond vectors for both dihedrals
// phi
// vb21 = r2 - r1
vb21x = x[i2][0] - x[i1][0];
vb21y = x[i2][1] - x[i1][1];
vb21z = x[i2][2] - x[i1][2];
vb12x = -1.0*vb21x;
vb12y = -1.0*vb21y;
vb12z = -1.0*vb21z;
vb32x = x[i3][0] - x[i2][0];
vb32y = x[i3][1] - x[i2][1];
vb32z = x[i3][2] - x[i2][2];
vb23x = -1.0*vb32x;
vb23y = -1.0*vb32y;
vb23z = -1.0*vb32z;
vb34x = x[i3][0] - x[i4][0];
vb34y = x[i3][1] - x[i4][1];
vb34z = x[i3][2] - x[i4][2];
// psi
// bond vectors same as for phi: vb32
vb43x = -1.0*vb34x;
vb43y = -1.0*vb34y;
vb43z = -1.0*vb34z;
vb45x = x[i4][0] - x[i5][0];
vb45y = x[i4][1] - x[i5][1];
vb45z = x[i4][2] - x[i5][2];
vb54x = -1.0*vb45x;
vb54y = -1.0*vb45y;
vb54z = -1.0*vb45z;
// calculate normal vectors for planes that define the dihedral angles
a1x = vb12y*vb23z - vb12z*vb23y;
a1y = vb12z*vb23x - vb12x*vb23z;
a1z = vb12x*vb23y - vb12y*vb23x;
b1x = vb43y*vb23z - vb43z*vb23y;
b1y = vb43z*vb23x - vb43x*vb23z;
b1z = vb43x*vb23y - vb43y*vb23x;
a2x = vb23y*vb34z - vb23z*vb34y;
a2y = vb23z*vb34x - vb23x*vb34z;
a2z = vb23x*vb34y - vb23y*vb34x;
b2x = vb45y*vb43z - vb45z*vb43y;
b2y = vb45z*vb43x - vb45x*vb43z;
b2z = vb45x*vb43y - vb45y*vb43x;
// calculate terms used later in calculations
r32 = sqrt(vb32x*vb32x + vb32y*vb32y + vb32z*vb32z);
a1sq = a1x*a1x + a1y*a1y + a1z*a1z;
b1sq = b1x*b1x + b1y*b1y + b1z*b1z;
r43 = sqrt(vb43x*vb43x + vb43y*vb43y + vb43z*vb43z);
a2sq = a2x*a2x + a2y*a2y + a2z*a2z;
b2sq = b2x*b2x + b2y*b2y + b2z*b2z;
//if (a1sq<0.0001 || b1sq<0.0001 || a2sq<0.0001 || b2sq<0.0001)
// printf("a1sq b1sq a2sq b2sq: %f %f %f %f \n",a1sq,b1sq,a2sq,b2sq);
if (a1sq<0.0001 || b1sq<0.0001 || a2sq<0.0001 || b2sq<0.0001) continue;
dpr21r32 = vb21x*vb32x + vb21y*vb32y + vb21z*vb32z;
dpr34r32 = vb34x*vb32x + vb34y*vb32y + vb34z*vb32z;
dpr32r43 = vb32x*vb43x + vb32y*vb43y + vb32z*vb43z;
dpr45r43 = vb45x*vb43x + vb45y*vb43y + vb45z*vb43z;
// calculate the backbone dihedral angles as VMD and GROMACS
phi = dihedral_angle_atan2(vb21x,vb21y,vb21z,a1x,a1y,a1z,b1x,b1y,b1z,r32);
psi = dihedral_angle_atan2(vb32x,vb32y,vb32z,a2x,a2y,a2z,b2x,b2y,b2z,r43);
if (phi == 180.0) phi= -180.0;
if (psi == 180.0) psi= -180.0;
phi1 = phi;
if (phi1 < 0.0) phi1 += 360.0;
psi1 = psi;
if (psi1 < 0.0) psi1 += 360.0;
// find the neighbor grid point index
li1 = int(((phi1+CMAPXMIN2)/CMAPDX)+((CMAPDIM*1.0)/2.0));
li2 = int(((psi1+CMAPXMIN2)/CMAPDX)+((CMAPDIM*1.0)/2.0));
li3 = int((phi-CMAPXMIN2)/CMAPDX);
li4 = int((psi-CMAPXMIN2)/CMAPDX);
mli3 = li3 % CMAPDIM;
mli4 = li4 % CMAPDIM;
mli31 = (li3+1) % CMAPDIM;
mli41 = (li4+1) %CMAPDIM;
mli1 = li1 % CMAPDIM;
mli2 = li2 % CMAPDIM;
mli11 = (li1+1) % CMAPDIM;
mli21 = (li2+1) %CMAPDIM;
t1 = type-1;
if (t1 < 0 || t1 > 5) error->all(FLERR,"Invalid CMAP crossterm_type");
// determine the values and derivatives for the grid square points
gs[0] = cmapgrid[t1][mli3][mli4];
gs[1] = cmapgrid[t1][mli31][mli4];
gs[2] = cmapgrid[t1][mli31][mli41];
gs[3] = cmapgrid[t1][mli3][mli41];
d1gs[0] = d1cmapgrid[t1][mli1][mli2];
d1gs[1] = d1cmapgrid[t1][mli11][mli2];
d1gs[2] = d1cmapgrid[t1][mli11][mli21];
d1gs[3] = d1cmapgrid[t1][mli1][mli21];
d2gs[0] = d2cmapgrid[t1][mli1][mli2];
d2gs[1] = d2cmapgrid[t1][mli11][mli2];
d2gs[2] = d2cmapgrid[t1][mli11][mli21];
d2gs[3] = d2cmapgrid[t1][mli1][mli21];
d12gs[0] = d12cmapgrid[t1][mli1][mli2];
d12gs[1] = d12cmapgrid[t1][mli11][mli2];
d12gs[2] = d12cmapgrid[t1][mli11][mli21];
d12gs[3] = d12cmapgrid[t1][mli1][mli21];
// calculate the cmap energy and the gradient (dE/dphi,dE/dpsi)
bc_interpol(phi,psi,li3,li4,gs,d1gs,d2gs,d12gs);
// sum up cmap energy contributions
engfraction = 0.2 * E;
if (i1 < nlocal) ecmap += engfraction;
if (i2 < nlocal) ecmap += engfraction;
if (i3 < nlocal) ecmap += engfraction;
if (i4 < nlocal) ecmap += engfraction;
if (i5 < nlocal) ecmap += engfraction;
// calculate the derivatives dphi/dr_i
dphidr1x = 1.0*r32/a1sq*a1x;
dphidr1y = 1.0*r32/a1sq*a1y;
dphidr1z = 1.0*r32/a1sq*a1z;
dphidr2x = -1.0*r32/a1sq*a1x - dpr21r32/a1sq/r32*a1x +
dpr34r32/b1sq/r32*b1x;
dphidr2y = -1.0*r32/a1sq*a1y - dpr21r32/a1sq/r32*a1y +
dpr34r32/b1sq/r32*b1y;
dphidr2z = -1.0*r32/a1sq*a1z - dpr21r32/a1sq/r32*a1z +
dpr34r32/b1sq/r32*b1z;
dphidr3x = dpr34r32/b1sq/r32*b1x - dpr21r32/a1sq/r32*a1x - r32/b1sq*b1x;
dphidr3y = dpr34r32/b1sq/r32*b1y - dpr21r32/a1sq/r32*a1y - r32/b1sq*b1y;
dphidr3z = dpr34r32/b1sq/r32*b1z - dpr21r32/a1sq/r32*a1z - r32/b1sq*b1z;
dphidr4x = r32/b1sq*b1x;
dphidr4y = r32/b1sq*b1y;
dphidr4z = r32/b1sq*b1z;
// calculate the derivatives dpsi/dr_i
dpsidr1x = 1.0*r43/a2sq*a2x;
dpsidr1y = 1.0*r43/a2sq*a2y;
dpsidr1z = 1.0*r43/a2sq*a2z;
dpsidr2x = r43/a2sq*a2x + dpr32r43/a2sq/r43*a2x - dpr45r43/b2sq/r43*b2x;
dpsidr2y = r43/a2sq*a2y + dpr32r43/a2sq/r43*a2y - dpr45r43/b2sq/r43*b2y;
dpsidr2z = r43/a2sq*a2z + dpr32r43/a2sq/r43*a2z - dpr45r43/b2sq/r43*b2z;
dpsidr3x = dpr45r43/b2sq/r43*b2x - dpr32r43/a2sq/r43*a2x - r43/b2sq*b2x;
dpsidr3y = dpr45r43/b2sq/r43*b2y - dpr32r43/a2sq/r43*a2y - r43/b2sq*b2y;
dpsidr3z = dpr45r43/b2sq/r43*b2z - dpr32r43/a2sq/r43*a2z - r43/b2sq*b2z;
dpsidr4x = r43/b2sq*b2x;
dpsidr4y = r43/b2sq*b2y;
dpsidr4z = r43/b2sq*b2z;
// calculate forces on cross-term atoms: F = -(dE/dPhi)*(dPhi/dr)
f1[0] = dEdPhi*dphidr1x;
f1[1] = dEdPhi*dphidr1y;
f1[2] = dEdPhi*dphidr1z;
f2[0] = dEdPhi*dphidr2x + dEdPsi*dpsidr1x;
f2[1] = dEdPhi*dphidr2y + dEdPsi*dpsidr1y;
f2[2] = dEdPhi*dphidr2z + dEdPsi*dpsidr1z;
f3[0] = -dEdPhi*dphidr3x - dEdPsi*dpsidr2x;
f3[1] = -dEdPhi*dphidr3y - dEdPsi*dpsidr2y;
f3[2] = -dEdPhi*dphidr3z - dEdPsi*dpsidr2z;
f4[0] = -dEdPhi*dphidr4x - dEdPsi*dpsidr3x;
f4[1] = -dEdPhi*dphidr4y - dEdPsi*dpsidr3y;
f4[2] = -dEdPhi*dphidr4z - dEdPsi*dpsidr3z;
f5[0] = -dEdPsi*dpsidr4x;
f5[1] = -dEdPsi*dpsidr4y;
f5[2] = -dEdPsi*dpsidr4z;
// apply force to each of the 5 atoms
if (i1 < nlocal) {
f[i1][0] += f1[0];
f[i1][1] += f1[1];
f[i1][2] += f1[2];
}
if (i2 < nlocal) {
f[i2][0] += f2[0];
f[i2][1] += f2[1];
f[i2][2] += f2[2];
}
if (i3 < nlocal) {
f[i3][0] += f3[0];
f[i3][1] += f3[1];
f[i3][2] += f3[2];
}
if (i4 < nlocal) {
f[i4][0] += f4[0];
f[i4][1] += f4[1];
f[i4][2] += f4[2];
}
if (i5 < nlocal) {
f[i5][0] += f5[0];
f[i5][1] += f5[1];
f[i5][2] += f5[2];
}
// tally energy and/or virial
if (evflag) {
nlist = 0;
if (i1 < nlocal) list[nlist++] = i1;
if (i2 < nlocal) list[nlist++] = i2;
if (i3 < nlocal) list[nlist++] = i3;
if (i4 < nlocal) list[nlist++] = i4;
if (i5 < nlocal) list[nlist++] = i5;
vcmap[0] = (vb12x*f1[0])+(vb32x*f3[0])+((vb43x+vb32x)*f4[0])+
((vb54x+vb43x+vb32x)*f5[0]);
vcmap[1] = (vb12y*f1[1])+(vb32y*f3[1])+((vb43y+vb32y)*f4[1])+
((vb54y+vb43y+vb32y)*f5[1]);
vcmap[2] = (vb12z*f1[2])+(vb32z*f3[2])+((vb43z+vb32z)*f4[2])+
((vb54z+vb43z+vb32z)*f5[2]);
vcmap[3] = (vb12x*f1[1])+(vb32x*f3[1])+((vb43x+vb32x)*f4[1])+
((vb54x+vb43x+vb32x)*f5[1]);
vcmap[4] = (vb12x*f1[2])+(vb32x*f3[2])+((vb43x+vb32x)*f4[2])+
((vb54x+vb43x+vb32x)*f5[2]);
vcmap[5] = (vb12y*f1[2])+(vb32y*f3[2])+((vb43y+vb32y)*f4[2])+
((vb54y+vb43y+vb32y)*f5[2]);
ev_tally(nlist,list,5.0,E,vcmap);
//ev_tally(5,list,nlocal,newton_bond,E,vcmap);
}
}
}
/* ---------------------------------------------------------------------- */
void FixCMAP::post_force_respa(int vflag, int ilevel, int iloop)
{
if (ilevel == nlevels_respa-1) post_force(vflag);
}
/* ---------------------------------------------------------------------- */
void FixCMAP::min_post_force(int vflag)
{
post_force(vflag);
}
/* ----------------------------------------------------------------------
energy of CMAP term
------------------------------------------------------------------------- */
double FixCMAP::compute_scalar()
{
double all;
MPI_Allreduce(&ecmap,&all,1,MPI_DOUBLE,MPI_SUM,world);
return all;
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// methods to read CMAP potential file, perform interpolation
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
void FixCMAP::read_grid_map(char *cmapfile)
{
char linebuf[MAXLINE];
char *chunk,*line;
int i1, i2, i3, i4, i5, i6, j1, j2, j3, j4, j5, j6, counter;
FILE *fp = NULL;
if (comm->me == 0) {
fp = force->open_potential(cmapfile);
if (fp == NULL) {
char str[128];
sprintf(str,"Cannot open fix cmap file %s",cmapfile);
error->one(FLERR,str);
}
}
for (int ix1 = 0; ix1 < 6; ix1++)
for (int ix2 = 0; ix2 < CMAPDIM; ix2++)
for (int ix3 = 0; ix3 < CMAPDIM; ix3++)
cmapgrid[ix1][ix2][ix3] = 0.0;
counter = 0;
i1 = i2 = i3 = i4 = i5 = i6 = 0;
j1 = j2 = j3 = j4 = j5 = j6 = 0;
int done = 0;
while (!done) {
// only read on rank 0 and broadcast to all other ranks
if (comm->me == 0)
done = (fgets(linebuf,MAXLINE,fp) == NULL);
MPI_Bcast(&done,1,MPI_INT,0,world);
if (done) continue;
MPI_Bcast(linebuf,MAXLINE,MPI_CHAR,0,world);
// remove leading whitespace
line = linebuf;
while (line && (*line == ' ' || *line == '\t' || *line == '\r')) ++line;
// skip if empty line or comment
if (!line || *line =='\n' || *line == '\0' || *line == '#') continue;
// read in the cmap grid point values
// NOTE: The order to read the 6 grid maps is HARD-CODED, thus errors
// will occur if content of the file "cmap.data" is altered
//
// Reading order of the maps:
// 1. Alanine map
// 2. Alanine before proline map
// 3. Proline map
// 4. Two adjacent prolines map
// 5. Glycine map
// 6. Glycine before proline map
chunk = strtok(line, " \r\n");
while (chunk != NULL) {
// alanine map
if (counter < CMAPDIM*CMAPDIM) {
cmapgrid[0][i1][j1] = atof(chunk);
chunk = strtok(NULL, " \r\n");
j1++;
if (j1 == CMAPDIM) {
j1 = 0;
i1++;
}
counter++;
}
// alanine-proline map
else if (counter >= CMAPDIM*CMAPDIM &&
counter < 2*CMAPDIM*CMAPDIM) {
cmapgrid[1][i2][j2]= atof(chunk);
chunk = strtok(NULL, " \r\n");
j2++;
if (j2 == CMAPDIM) {
j2 = 0;
i2++;
}
counter++;
}
// proline map
else if (counter >= 2*CMAPDIM*CMAPDIM &&
counter < 3*CMAPDIM*CMAPDIM) {
cmapgrid[2][i3][j3] = atof(chunk);
chunk = strtok(NULL, " \r\n");
j3++;
if (j3 == CMAPDIM) {
j3 = 0;
i3++;
}
counter++;
}
// 2 adjacent prolines map
else if (counter >= 3*CMAPDIM*CMAPDIM &&
counter < 4*CMAPDIM*CMAPDIM) {
cmapgrid[3][i4][j4] = atof(chunk);
chunk = strtok(NULL, " \r\n");
j4++;
if (j4 == CMAPDIM) {
j4 = 0;
i4++;
}
counter++;
}
// glycine map
else if (counter >= 4*CMAPDIM*CMAPDIM &&
counter < 5*CMAPDIM*CMAPDIM) {
cmapgrid[4][i5][j5] = atof(chunk);
chunk = strtok(NULL, " \r\n");
j5++;
if (j5 == CMAPDIM) {
j5 = 0;
i5++;
}
counter++;
}
// glycine-proline map
else if (counter >= 5*CMAPDIM*CMAPDIM &&
counter < 6*CMAPDIM*CMAPDIM) {
cmapgrid[5][i6][j6] = atof(chunk);
chunk = strtok(NULL, " \r\n");
j6++;
if (j6 == CMAPDIM) {
j6 = 0;
i6++;
}
counter++;
}
else break;
}
}
if (comm->me == 0) fclose(fp);
}
/* ---------------------------------------------------------------------- */
void FixCMAP::spline(double *y, double *ddy, int n)
{
// create the 2nd dervatives of a taublated function y_i(x_i)
// at the tabulated points
int i, j;
double p, *u;
memory->create(u,n-1,"cmap:u");
ddy[0] = u[0] = 0.0;
for (i = 1; i <= n-2; i++) {
p = 1.0/(ddy[i-1]+4.0);
ddy[i] = -p;
u[i] = ((((6.0*y[i+1])-(12.0*y[i])+(6.0*y[i-1]))/(CMAPDX*CMAPDX))-u[i-1])*p;
}
ddy[n-1] = 0.0;
for (j = n-2; j >= 0; j--)
ddy[j] = ddy[j]*ddy[j+1] + u[j];
memory->destroy(u);
}
/* ---------------------------------------------------------------------- */
void FixCMAP::spl_interpolate(double x, double *y, double *ddy, double &yo,
double &dyo)
{
// perform a 1D cubic spline interpolation
int ix;
double a,b,a1,b1,a2,b2;
ix = int((x-CMAPXMIN)/CMAPDX-(1./2.));
a = (CMAPXMIN+(ix*1.0)*CMAPDX-x)/CMAPDX;
b = (x-CMAPXMIN-(((ix-1)*1.0)*CMAPDX))/CMAPDX;
a1 = a*a*a-a;
b1 = b*b*b-b;
a2 = 3.0*a*a-1.0;
b2 = 3.0*b*b-1.0;
yo = a*y[ix]+b*y[ix+1]+(a1*ddy[ix]+b1*ddy[ix+1])*(CMAPDX*CMAPDX)/6.0;
dyo = (y[ix+1]-y[ix])/CMAPDX-a2/6.0*CMAPDX*ddy[ix]+b2/6.0*CMAPDX*ddy[ix+1];
}
/* ---------------------------------------------------------------------- */
void FixCMAP::set_map_derivatives(double **map, double **d1yo, double **d2yo,
double **d12yo)
{
// precompute the gradient and cross-derivatives of the map grid points.
// use the bicubic spline to calculate the derivatives
int i, j, k, ii, jj, xm, p;
double phi, psi, d1y, d2y, d12y, tyyk,tdyk;
double *tmp_y, *tmp_dy, *tmp_ddy, **tmap, **tddmap;
int ix;
double a,b,a1,b1,a2,b2;
xm = CMAPDIM/2;
p = CMAPDIM;
d1y = 0.;
d2y = 0.;
d12y = 0.;
memory->create(tmp_y,CMAPDIM*2,"cmap:tmp_y");
memory->create(tmp_dy,CMAPDIM*2,"cmap:tmp_dy");
memory->create(tmp_ddy,CMAPDIM*2,"cmap:tmp_ddy");
memory->create(tmap,CMAPDIM*2,CMAPDIM*2,"cmap:tmap");
memory->create(tddmap,CMAPDIM*2,CMAPDIM*2,"cmap:tddmap");
// periodically expand the original map
// use the expanded map for bicubic spline interpolation,
// which is used to obtain the derivatives
// actual interpolation is done with bicubic interpolation
for (i = 0; i < CMAPDIM*2; i++) {
ii = ((i+CMAPDIM-xm)%CMAPDIM);
for (j = 0; j < CMAPDIM*2; j++) {
jj = ((j+CMAPDIM-xm)%CMAPDIM);
tmap[i][j] = map[ii][jj];
}
}
for (i = 0; i < CMAPDIM*2; i++)
spline(tmap[i], tddmap[i], CMAPDIM*2);
for (i = xm; i < CMAPDIM+xm; i++) {
phi = (i-xm)*CMAPDX-180.0;
for (j = xm; j < CMAPDIM+xm; j++) {
psi = (j-xm)*CMAPDX-180.0;
ix = int((psi-CMAPXMIN)/CMAPDX);
a = (CMAPXMIN+((ix+1)*1.0)*CMAPDX-psi)/CMAPDX;
b = (psi-CMAPXMIN-((ix)*1.0)*CMAPDX)/CMAPDX;
a1 = a*a*a-a;
b1 = b*b*b-b;
a2 = 3.0*a*a-1.0;
b2 = 3.0*b*b-1.0;
for (k = 0; k < CMAPDIM*2; k++) {
tyyk = tmp_y[k];
tdyk = tmp_dy[k];
tyyk = a*tmap[k][ix]+b*tmap[k][ix+1]+
(a1*tddmap[k][ix]+b1*tddmap[k][ix+1])*(CMAPDX*CMAPDX)/6.0;
tdyk = (tmap[k][ix+1]-tmap[k][ix])/CMAPDX-
(a2/6.0*CMAPDX*tddmap[k][ix])+(b2/6.0*CMAPDX*tddmap[k][ix+1]);
tmp_y[k] = tyyk;
tmp_dy[k] = tdyk;
}
spline(tmp_y,tmp_ddy,CMAPDIM+xm+xm);
ix = int((phi-CMAPXMIN)/CMAPDX);
a = (CMAPXMIN+((ix+1)*1.0)*CMAPDX-phi)/CMAPDX;
b = (phi-CMAPXMIN-(ix*1.0)*CMAPDX)/CMAPDX;
a1 = a*a*a-a;
b1 = b*b*b-b;
a2 = 3.0*a*a-1.0;
b2 = 3.0*b*b-1.0;
d1y = (tmp_y[ix+1]-tmp_y[ix])/CMAPDX-
a2/6.0*CMAPDX*tmp_ddy[ix]+b2/6.0*CMAPDX*tmp_ddy[ix+1];
spline(tmp_dy,tmp_ddy,CMAPDIM+xm+xm);
ix = int((phi-CMAPXMIN)/CMAPDX);
a = (CMAPXMIN+((ix+1)*1.0)*CMAPDX-phi)/CMAPDX;
b = (phi-CMAPXMIN-(ix*1.0)*CMAPDX)/CMAPDX;
a1 = a*a*a-a;
b1 = b*b*b-b;
a2 = 3.0*a*a-1.0;
b2 = 3.0*b*b-1.0;
d2y = a*tmp_dy[ix]+b*tmp_dy[ix+1]+
(a1*tmp_ddy[ix]+b1*tmp_ddy[ix+1])*(CMAPDX*CMAPDX)/6.0;
d12y = (tmp_dy[ix+1]-tmp_dy[ix])/CMAPDX-
a2/6.0*CMAPDX*tmp_ddy[ix]+b2/6.0*CMAPDX*tmp_ddy[ix+1];
d1yo[i%p][j%p] = d1y;
d2yo[i%p][j%p] = d2y;
d12yo[i%p][j%p] = d12y;
}
}
memory->destroy(tmp_y);
memory->destroy(tmp_dy);
memory->destroy(tmp_ddy);
memory->destroy(tmap);
memory->destroy(tddmap);
}
/* ---------------------------------------------------------------------- */
double FixCMAP::dihedral_angle_atan2(double fx, double fy, double fz,
double ax, double ay, double az,
double bx, double by, double bz,
double absg)
{
// calculate the dihedral angle
double angle, arg1, arg2;
arg1 = absg*(fx*bx+fy*by+fz*bz);
arg2 = ax*bx+ay*by+az*bz;
if (arg1 == 0 && arg2 == 0)
error->all(FLERR,"CMAP: atan2 function cannot take 2 zero arguments");
else {
angle = atan2(arg1,arg2);
angle = angle*180.0/MY_PI;
}
return angle;
}
/* ---------------------------------------------------------------------- */
void FixCMAP::bc_coeff(double *gs, double *d1gs, double *d2gs, double *d12gs)
{
// calculate the bicubic interpolation coefficients c_ij
static int wt[16][16] =
{ {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0},
{-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1, 0, 0, 0, 0},
{2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0,-3, 0, 0, 3, 0, 0, 0, 0,-2, 0, 0,-1},
{0, 0, 0, 0, 2, 0, 0,-2, 0, 0, 0, 0, 1, 0, 0, 1},
{-3, 3, 0, 0,-2,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0,-2,-1, 0, 0},
{9,-9, 9,-9, 6, 3,-3,-6, 6,-6,-3, 3, 4, 2, 1, 2},
{-6, 6,-6, 6,-4,-2, 2, 4,-3, 3, 3,-3,-2,-1,-1,-2},
{2,-2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 2,-2, 0, 0, 1, 1, 0, 0},
{-6, 6,-6, 6,-3,-3, 3, 3,-4, 4, 2,-2,-2,-2,-1,-1},
{4,-4, 4,-4, 2, 2,-2,-2, 2,-2,-2, 2, 1, 1, 1, 1}
};
int i, j, k, in;
double xx, x[16];
for (i = 0; i < 4; i++) {
x[i] = gs[i];
x[i+4] = d1gs[i]*CMAPDX;
x[i+8] = d2gs[i]*CMAPDX;
x[i+12] = d12gs[i]*CMAPDX*CMAPDX;
}
in = 0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
xx = 0.0;
for (k = 0; k < 16; k++) xx += wt[in][k]*x[k];
in++;
cij[i][j] = xx;
}
}
}
/* ---------------------------------------------------------------------- */
void FixCMAP::bc_interpol(double x1, double x2, int low1, int low2, double *gs,
double *d1gs, double *d2gs, double *d12gs)
{
// for a given point of interest and its corresponding grid square values,
// gradients and cross-derivatives
// calculate the interpolated value of the point of interest (POI)
int i;
double t, u, gs1l, gs2l;
// set the interpolation coefficients
bc_coeff(gs,d1gs,d2gs,d12gs);
gs1l = g_axis[low1];
gs2l = g_axis[low2];
t = (x1-gs1l)/CMAPDX;
u = (x2-gs2l)/CMAPDX;
E = dEdPhi = dEdPsi = 0.0;
for (i = 3; i >= 0; i--) {
E = t*E + ((cij[i][3]*u+cij[i][2])*u+cij[i][1])*u+cij[i][0];
dEdPhi = u*dEdPhi + (3.0*cij[3][i]*t+2.0*cij[2][i])*t+cij[1][i];
dEdPsi = t*dEdPsi + (3.0*cij[i][3]*u+2.0*cij[i][2])*u+cij[i][1];
}
dEdPhi *= (180.0/MY_PI/CMAPDX);
dEdPsi *= (180.0/MY_PI/CMAPDX);
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// methods to read and write data file
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
void FixCMAP::read_data_header(char *line)
{
if (strstr(line,"crossterms")) {
sscanf(line,BIGINT_FORMAT,&ncmap);
} else error->all(FLERR,"Invalid read data header line for fix cmap");
// didn't set in constructor b/c this fix could be defined
// before newton command
newton_bond = force->newton_bond;
}
/* ----------------------------------------------------------------------
unpack N lines in buf from section of data file labeled by keyword
id_offset is applied to atomID fields if multiple data files are read
store CMAP interactions as if newton_bond = OFF, even if actually ON
------------------------------------------------------------------------- */
void FixCMAP::read_data_section(char *keyword, int n, char *buf,
tagint id_offset)
{
int m,tmp,itype;
tagint atom1,atom2,atom3,atom4,atom5;
char *next;
next = strchr(buf,'\n');
*next = '\0';
int nwords = atom->count_words(buf);
*next = '\n';
if (nwords != 7) {
char str[128];
sprintf(str,"Incorrect %s format in data file",keyword);
error->all(FLERR,str);
}
// loop over lines of CMAP crossterms
// tokenize the line into values
// add crossterm to one of my atoms, depending on newton_bond
for (int i = 0; i < n; i++) {
next = strchr(buf,'\n');
*next = '\0';
sscanf(buf,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT
" " TAGINT_FORMAT " " TAGINT_FORMAT,
&tmp,&itype,&atom1,&atom2,&atom3,&atom4,&atom5);
atom1 += id_offset;
atom2 += id_offset;
atom3 += id_offset;
atom4 += id_offset;
atom5 += id_offset;
if ((m = atom->map(atom1)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
crossterm_atom3[m][num_crossterm[m]] = atom3;
crossterm_atom4[m][num_crossterm[m]] = atom4;
crossterm_atom5[m][num_crossterm[m]] = atom5;
num_crossterm[m]++;
}
if ((m = atom->map(atom2)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
crossterm_atom3[m][num_crossterm[m]] = atom3;
crossterm_atom4[m][num_crossterm[m]] = atom4;
crossterm_atom5[m][num_crossterm[m]] = atom5;
num_crossterm[m]++;
}
if ((m = atom->map(atom3)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
crossterm_atom3[m][num_crossterm[m]] = atom3;
crossterm_atom4[m][num_crossterm[m]] = atom4;
crossterm_atom5[m][num_crossterm[m]] = atom5;
num_crossterm[m]++;
}
if ((m = atom->map(atom4)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
crossterm_atom3[m][num_crossterm[m]] = atom3;
crossterm_atom4[m][num_crossterm[m]] = atom4;
crossterm_atom5[m][num_crossterm[m]] = atom5;
num_crossterm[m]++;
}
if ((m = atom->map(atom5)) >= 0) {
if (num_crossterm[m] == CMAPMAX)
error->one(FLERR,"Too many CMAP crossterms for one atom");
crossterm_type[m][num_crossterm[m]] = itype;
crossterm_atom1[m][num_crossterm[m]] = atom1;
crossterm_atom2[m][num_crossterm[m]] = atom2;
crossterm_atom3[m][num_crossterm[m]] = atom3;
crossterm_atom4[m][num_crossterm[m]] = atom4;
crossterm_atom5[m][num_crossterm[m]] = atom5;
num_crossterm[m]++;
}
buf = next + 1;
}
}
/* ---------------------------------------------------------------------- */
bigint FixCMAP::read_data_skip_lines(char *keyword)
{
return ncmap;
}
/* ----------------------------------------------------------------------
write Mth header line to file
only called by proc 0
------------------------------------------------------------------------- */
void FixCMAP::write_data_header(FILE *fp, int mth)
{
fprintf(fp,BIGINT_FORMAT " cmap crossterms\n",ncmap);
}
/* ----------------------------------------------------------------------
return size I own for Mth data section
# of data sections = 1 for this fix
nx = # of crossterms owned by my local atoms
if newton_bond off, atom only owns crossterm if it is atom3
ny = columns = type + 5 atom IDs
------------------------------------------------------------------------- */
void FixCMAP::write_data_section_size(int mth, int &nx, int &ny)
{
int i,m;
tagint *tag = atom->tag;
int nlocal = atom->nlocal;
nx = 0;
for (i = 0; i < nlocal; i++)
for (m = 0; m < num_crossterm[i]; m++)
if (crossterm_atom3[i][m] == tag[i]) nx++;
ny = 6;
}
/* ----------------------------------------------------------------------
pack values for Mth data section into 2d buf
buf allocated by caller as owned crossterms by 6
------------------------------------------------------------------------- */
void FixCMAP::write_data_section_pack(int mth, double **buf)
{
int i,m;
// 1st column = CMAP type
// 2nd-6th columns = 5 atom IDs
tagint *tag = atom->tag;
int nlocal = atom->nlocal;
int n = 0;
for (i = 0; i < nlocal; i++) {
for (m = 0; m < num_crossterm[i]; m++) {
if (crossterm_atom3[i][m] != tag[i]) continue;
buf[n][0] = ubuf(crossterm_type[i][m]).d;
buf[n][1] = ubuf(crossterm_atom1[i][m]).d;
buf[n][2] = ubuf(crossterm_atom2[i][m]).d;
buf[n][3] = ubuf(crossterm_atom3[i][m]).d;
buf[n][4] = ubuf(crossterm_atom4[i][m]).d;
buf[n][5] = ubuf(crossterm_atom5[i][m]).d;
n++;
}
}
}
/* ----------------------------------------------------------------------
write section keyword for Mth data section to file
use Molecules or Charges if that is only field, else use fix ID
only called by proc 0
------------------------------------------------------------------------- */
void FixCMAP::write_data_section_keyword(int mth, FILE *fp)
{
fprintf(fp,"\nCMAP\n\n");
}
/* ----------------------------------------------------------------------
write N lines from buf to file
convert buf fields to int or double depending on styles
index can be used to prepend global numbering
only called by proc 0
------------------------------------------------------------------------- */
void FixCMAP::write_data_section(int mth, FILE *fp,
int n, double **buf, int index)
{
for (int i = 0; i < n; i++)
fprintf(fp,"%d %d " TAGINT_FORMAT " " TAGINT_FORMAT
" " TAGINT_FORMAT " " TAGINT_FORMAT " " TAGINT_FORMAT "\n",
index+i,(int) ubuf(buf[i][0]).i,(tagint) ubuf(buf[i][1]).i,
(tagint) ubuf(buf[i][2]).i,(tagint) ubuf(buf[i][3]).i,
(tagint) ubuf(buf[i][4]).i,(tagint) ubuf(buf[i][5]).i);
}
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
// methods for restart and communication
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
/* ----------------------------------------------------------------------
pack entire state of Fix into one write
------------------------------------------------------------------------- */
void FixCMAP::write_restart(FILE *fp)
{
if (comm->me == 0) {
int size = sizeof(bigint);
fwrite(&size,sizeof(int),1,fp);
fwrite(&ncmap,sizeof(bigint),1,fp);
}
}
/* ----------------------------------------------------------------------
use state info from restart file to restart the Fix
------------------------------------------------------------------------- */
void FixCMAP::restart(char *buf)
{
ncmap = *((bigint *) buf);
}
/* ----------------------------------------------------------------------
pack values in local atom-based arrays for restart file
------------------------------------------------------------------------- */
int FixCMAP::pack_restart(int i, double *buf)
{
int n = 1;
for (int m = 0; m < num_crossterm[i]; m++) {
buf[n++] = ubuf(MAX(crossterm_type[i][m],-crossterm_type[i][m])).d;
buf[n++] = ubuf(crossterm_atom1[i][m]).d;
buf[n++] = ubuf(crossterm_atom2[i][m]).d;
buf[n++] = ubuf(crossterm_atom3[i][m]).d;
buf[n++] = ubuf(crossterm_atom4[i][m]).d;
buf[n++] = ubuf(crossterm_atom5[i][m]).d;
}
buf[0] = n;
return n;
}
/* ----------------------------------------------------------------------
unpack values from atom->extra array to restart the fix
------------------------------------------------------------------------- */
void FixCMAP::unpack_restart(int nlocal, int nth)
{
double **extra = atom->extra;
// skip to Nth set of extra values
int n = 0;
for (int i = 0; i < nth; i++) n += static_cast<int> (extra[nlocal][n]);
int count = static_cast<int> (extra[nlocal][n++]);
num_crossterm[nlocal] = (count-1)/6;
for (int m = 0; m < num_crossterm[nlocal]; m++) {
crossterm_type[nlocal][m] = (int) ubuf(extra[nlocal][n++]).i;
crossterm_atom1[nlocal][m] = (tagint) ubuf(extra[nlocal][n++]).i;
crossterm_atom2[nlocal][m] = (tagint) ubuf(extra[nlocal][n++]).i;
crossterm_atom3[nlocal][m] = (tagint) ubuf(extra[nlocal][n++]).i;
crossterm_atom4[nlocal][m] = (tagint) ubuf(extra[nlocal][n++]).i;
crossterm_atom5[nlocal][m] = (tagint) ubuf(extra[nlocal][n++]).i;
}
}
/* ----------------------------------------------------------------------
maxsize of any atom's restart data
------------------------------------------------------------------------- */
int FixCMAP::maxsize_restart()
{
return 1 + CMAPMAX*6;
}
/* ----------------------------------------------------------------------
size of atom nlocal's restart data
------------------------------------------------------------------------- */
int FixCMAP::size_restart(int nlocal)
{
return 1 + num_crossterm[nlocal]*6;
}
/* ----------------------------------------------------------------------
allocate atom-based array
------------------------------------------------------------------------- */
void FixCMAP::grow_arrays(int nmax)
{
num_crossterm = memory->grow(num_crossterm,nmax,"cmap:num_crossterm");
crossterm_type = memory->grow(crossterm_type,nmax,CMAPMAX,
"cmap:crossterm_type");
crossterm_atom1 = memory->grow(crossterm_atom1,nmax,CMAPMAX,
"cmap:crossterm_atom1");
crossterm_atom2 = memory->grow(crossterm_atom2,nmax,CMAPMAX,
"cmap:crossterm_atom2");
crossterm_atom3 = memory->grow(crossterm_atom3,nmax,CMAPMAX,
"cmap:crossterm_atom3");
crossterm_atom4 = memory->grow(crossterm_atom4,nmax,CMAPMAX,
"cmap:crossterm_atom4");
crossterm_atom5 = memory->grow(crossterm_atom5,nmax,CMAPMAX,
"cmap:crossterm_atom5");
// must initialize num_crossterm to 0 for added atoms
// may never be set for some atoms when data file is read
for (int i = nmax_previous; i < nmax; i++) num_crossterm[i] = 0;
nmax_previous = nmax;
}
/* ----------------------------------------------------------------------
copy values within local atom-based array
------------------------------------------------------------------------- */
void FixCMAP::copy_arrays(int i, int j, int delflag)
{
num_crossterm[j] = num_crossterm[i];
for (int k = 0; k < num_crossterm[j]; k++){
crossterm_type[j][k] = crossterm_type[i][k];
crossterm_atom1[j][k] = crossterm_atom1[i][k];
crossterm_atom2[j][k] = crossterm_atom2[i][k];
crossterm_atom3[j][k] = crossterm_atom3[i][k];
crossterm_atom4[j][k] = crossterm_atom4[i][k];
crossterm_atom5[j][k] = crossterm_atom5[i][k];
}
}
/* ----------------------------------------------------------------------
initialize one atom's array values, called when atom is created
------------------------------------------------------------------------- */
void FixCMAP::set_arrays(int i)
{
num_crossterm[i] = 0;
}
/* ----------------------------------------------------------------------
pack values in local atom-based array for exchange with another proc
------------------------------------------------------------------------- */
int FixCMAP::pack_exchange(int i, double *buf)
{
int n = 0;
buf[n++] = ubuf(num_crossterm[i]).d;
for (int m = 0; m < num_crossterm[i]; m++) {
buf[n++] = ubuf(crossterm_type[i][m]).d;
buf[n++] = ubuf(crossterm_atom1[i][m]).d;
buf[n++] = ubuf(crossterm_atom2[i][m]).d;
buf[n++] = ubuf(crossterm_atom3[i][m]).d;
buf[n++] = ubuf(crossterm_atom4[i][m]).d;
buf[n++] = ubuf(crossterm_atom5[i][m]).d;
}
return n;
}
/* ----------------------------------------------------------------------
unpack values in local atom-based array from exchange with another proc
------------------------------------------------------------------------- */
int FixCMAP::unpack_exchange(int nlocal, double *buf)
{
int n = 0;
num_crossterm[nlocal] = (int) ubuf(buf[n++]).i;
for (int m = 0; m < num_crossterm[nlocal]; m++) {
crossterm_type[nlocal][m] = (int) ubuf(buf[n++]).i;
crossterm_atom1[nlocal][m] = (tagint) ubuf(buf[n++]).i;
crossterm_atom2[nlocal][m] = (tagint) ubuf(buf[n++]).i;
crossterm_atom3[nlocal][m] = (tagint) ubuf(buf[n++]).i;
crossterm_atom4[nlocal][m] = (tagint) ubuf(buf[n++]).i;
crossterm_atom5[nlocal][m] = (tagint) ubuf(buf[n++]).i;
}
return n;
}
/* ----------------------------------------------------------------------
memory usage of local atom-based arrays
------------------------------------------------------------------------- */
double FixCMAP::memory_usage()
{
int nmax = atom->nmax;
double bytes = nmax * sizeof(int); // num_crossterm
bytes += nmax*CMAPMAX * sizeof(int); // crossterm_type
bytes += 5*nmax*CMAPMAX * sizeof(int); // crossterm_atom 12345
bytes += maxcrossterm*6 * sizeof(int); // crosstermlist
return bytes;
}
Event Timeline
Log In to Comment