diff --git a/src/USER-REAXC/fix_qeq_reax.cpp b/src/USER-REAXC/fix_qeq_reax.cpp index c0ccb01ca..c88514071 100644 --- a/src/USER-REAXC/fix_qeq_reax.cpp +++ b/src/USER-REAXC/fix_qeq_reax.cpp @@ -1,1042 +1,1039 @@ /* ---------------------------------------------------------------------- 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 author: Hasan Metin Aktulga, Purdue University (now at Lawrence Berkeley National Laboratory, hmaktulga@lbl.gov) Hybrid and sub-group capabilities: Ray Shan (Sandia) ------------------------------------------------------------------------- */ #include "math.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "fix_qeq_reax.h" #include "pair_reax_c.h" #include "atom.h" #include "comm.h" #include "domain.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "update.h" #include "force.h" #include "group.h" #include "pair.h" #include "respa.h" #include "memory.h" #include "citeme.h" #include "error.h" #include "reaxc_defs.h" using namespace LAMMPS_NS; using namespace FixConst; #define EV_TO_KCAL_PER_MOL 14.4 //#define DANGER_ZONE 0.95 //#define LOOSE_ZONE 0.7 #define SQR(x) ((x)*(x)) #define CUBE(x) ((x)*(x)*(x)) #define MIN_NBRS 100 static const char cite_fix_qeq_reax[] = "fix qeq/reax command:\n\n" "@Article{Aktulga12,\n" " author = {H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama},\n" " title = {Parallel reactive molecular dynamics: Numerical methods and algorithmic techniques},\n" " journal = {Parallel Computing},\n" " year = 2012,\n" " volume = 38,\n" " pages = {245--259}\n" "}\n\n"; /* ---------------------------------------------------------------------- */ FixQEqReax::FixQEqReax(LAMMPS *lmp, int narg, char **arg) : Fix(lmp, narg, arg) { if (lmp->citeme) lmp->citeme->add(cite_fix_qeq_reax); if (narg != 8) error->all(FLERR,"Illegal fix qeq/reax command"); nevery = force->inumeric(FLERR,arg[3]); swa = force->numeric(FLERR,arg[4]); swb = force->numeric(FLERR,arg[5]); tolerance = force->numeric(FLERR,arg[6]); pertype_parameters(arg[7]); shld = NULL; n = n_cap = 0; N = nmax = 0; m_fill = m_cap = 0; pack_flag = 0; s = NULL; t = NULL; nprev = 5; Hdia_inv = NULL; b_s = NULL; b_t = NULL; b_prc = NULL; b_prm = NULL; // CG p = NULL; q = NULL; r = NULL; d = NULL; // H matrix H.firstnbr = NULL; H.numnbrs = NULL; H.jlist = NULL; H.val = NULL; // perform initial allocation of atom-based arrays // register with Atom class s_hist = t_hist = NULL; grow_arrays(atom->nmax); atom->add_callback(0); for( int i = 0; i < atom->nmax; i++ ) for (int j = 0; j < nprev; ++j ) s_hist[i][j] = t_hist[i][j] = 0; reaxc = NULL; reaxc = (PairReaxC *) force->pair_match("reax/c",1); } /* ---------------------------------------------------------------------- */ FixQEqReax::~FixQEqReax() { // unregister callbacks to this fix from Atom class atom->delete_callback(id,0); memory->destroy(s_hist); memory->destroy(t_hist); deallocate_storage(); deallocate_matrix(); memory->destroy(shld); if (!reaxflag) { memory->destroy(chi); memory->destroy(eta); memory->destroy(gamma); } } /* ---------------------------------------------------------------------- */ int FixQEqReax::setmask() { int mask = 0; mask |= PRE_FORCE; mask |= MIN_PRE_FORCE; return mask; } /* ---------------------------------------------------------------------- */ void FixQEqReax::pertype_parameters(char *arg) { if (strcmp(arg,"reax/c") == 0) { reaxflag = 1; Pair *pair = force->pair_match("reax/c",1); if (pair == NULL) error->all(FLERR,"No pair reax/c for fix qeq/reax"); int tmp; chi = (double *) pair->extract("chi",tmp); eta = (double *) pair->extract("eta",tmp); gamma = (double *) pair->extract("gamma",tmp); if (chi == NULL || eta == NULL || gamma == NULL) error->all(FLERR, "Fix qeq/reax could not extract params from pair reax/c"); return; } int i,itype,ntypes; double v1,v2,v3; FILE *pf; reaxflag = 0; ntypes = atom->ntypes; memory->create(chi,ntypes+1,"qeq/reax:chi"); memory->create(eta,ntypes+1,"qeq/reax:eta"); memory->create(gamma,ntypes+1,"qeq/reax:gamma"); if (comm->me == 0) { if ((pf = fopen(arg,"r")) == NULL) error->one(FLERR,"Fix qeq/reax parameter file could not be found"); for (i = 1; i <= ntypes && !feof(pf); i++) { fscanf(pf,"%d %lg %lg %lg",&itype,&v1,&v2,&v3); if (itype < 1 || itype > ntypes) error->one(FLERR,"Fix qeq/reax invalid atom type in param file"); chi[itype] = v1; eta[itype] = v2; gamma[itype] = v3; } if (i <= ntypes) error->one(FLERR,"Invalid param file for fix qeq/reax"); fclose(pf); } MPI_Bcast(&chi[1],ntypes,MPI_DOUBLE,0,world); MPI_Bcast(&eta[1],ntypes,MPI_DOUBLE,0,world); MPI_Bcast(&gamma[1],ntypes,MPI_DOUBLE,0,world); } /* ---------------------------------------------------------------------- */ void FixQEqReax::allocate_storage() { nmax = atom->nmax; memory->create(s,nmax,"qeq:s"); memory->create(t,nmax,"qeq:t"); memory->create(Hdia_inv,nmax,"qeq:Hdia_inv"); memory->create(b_s,nmax,"qeq:b_s"); memory->create(b_t,nmax,"qeq:b_t"); memory->create(b_prc,nmax,"qeq:b_prc"); memory->create(b_prm,nmax,"qeq:b_prm"); memory->create(p,nmax,"qeq:p"); memory->create(q,nmax,"qeq:q"); memory->create(r,nmax,"qeq:r"); memory->create(d,nmax,"qeq:d"); } /* ---------------------------------------------------------------------- */ void FixQEqReax::deallocate_storage() { memory->destroy(s); memory->destroy(t); memory->destroy( Hdia_inv ); memory->destroy( b_s ); memory->destroy( b_t ); memory->destroy( b_prc ); memory->destroy( b_prm ); memory->destroy( p ); memory->destroy( q ); memory->destroy( r ); memory->destroy( d ); } /* ---------------------------------------------------------------------- */ void FixQEqReax::reallocate_storage() { deallocate_storage(); allocate_storage(); init_storage(); } /* ---------------------------------------------------------------------- */ void FixQEqReax::allocate_matrix() { int i,ii,inum,m; int *ilist, *numneigh; int mincap; double safezone; if( reaxflag ) { mincap = reaxc->system->mincap; safezone = reaxc->system->safezone; } else { mincap = MIN_CAP; safezone = SAFE_ZONE; } n = atom->nlocal; n_cap = MAX( (int)(n * safezone), mincap ); // determine the total space for the H matrix if (reaxc) { inum = reaxc->list->inum; ilist = reaxc->list->ilist; numneigh = reaxc->list->numneigh; } else { inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; } m = 0; for( ii = 0; ii < inum; ii++ ) { i = ilist[ii]; m += numneigh[i]; } m_cap = MAX( (int)(m * safezone), mincap * MIN_NBRS ); H.n = n_cap; H.m = m_cap; memory->create(H.firstnbr,n_cap,"qeq:H.firstnbr"); memory->create(H.numnbrs,n_cap,"qeq:H.numnbrs"); memory->create(H.jlist,m_cap,"qeq:H.jlist"); memory->create(H.val,m_cap,"qeq:H.val"); } /* ---------------------------------------------------------------------- */ void FixQEqReax::deallocate_matrix() { memory->destroy( H.firstnbr ); memory->destroy( H.numnbrs ); memory->destroy( H.jlist ); memory->destroy( H.val ); } /* ---------------------------------------------------------------------- */ void FixQEqReax::reallocate_matrix() { deallocate_matrix(); allocate_matrix(); } /* ---------------------------------------------------------------------- */ void FixQEqReax::init() { if (!atom->q_flag) error->all(FLERR,"Fix qeq/reax requires atom attribute q"); if (!force->pair_match("reax/c",1)) error->all(FLERR,"Must use pair_style reax/c with fix qeq/reax"); ngroup = group->count(igroup); if (ngroup == 0) error->all(FLERR,"Fix qeq/reax group has no atoms"); /* if (reaxc) if (ngroup != reaxc->ngroup) error->all(FLERR,"Fix qeq/reax group and pair reax/c have " "different numbers of atoms"); */ // need a half neighbor list w/ Newton off and ghost neighbors // built whenever re-neighboring occurs int irequest = neighbor->request(this); neighbor->requests[irequest]->pair = 0; neighbor->requests[irequest]->fix = 1; neighbor->requests[irequest]->newton = 2; neighbor->requests[irequest]->ghost = 1; init_shielding(); init_taper(); if (strstr(update->integrate_style,"respa")) nlevels_respa = ((Respa *) update->integrate)->nlevels; } /* ---------------------------------------------------------------------- */ void FixQEqReax::init_list(int id, NeighList *ptr) { list = ptr; } /* ---------------------------------------------------------------------- */ void FixQEqReax::init_shielding() { int i,j; int ntypes; ntypes = atom->ntypes; memory->create(shld,ntypes+1,ntypes+1,"qeq:shileding"); for( i = 1; i <= ntypes; ++i ) for( j = 1; j <= ntypes; ++j ) shld[i][j] = pow( gamma[i] * gamma[j], -1.5 ); } /* ---------------------------------------------------------------------- */ void FixQEqReax::init_taper() { double d7, swa2, swa3, swb2, swb3; if (fabs(swa) > 0.01 && comm->me == 0) error->warning(FLERR,"Fix qeq/reax has non-zero lower Taper radius cutoff"); if (swb < 0) error->all(FLERR, "Fix qeq/reax has negative upper Taper radius cutoff"); else if (swb < 5 && comm->me == 0) error->warning(FLERR,"Fix qeq/reax has very low Taper radius cutoff"); d7 = pow( swb - swa, 7 ); swa2 = SQR( swa ); swa3 = CUBE( swa ); swb2 = SQR( swb ); swb3 = CUBE( swb ); Tap[7] = 20.0 / d7; Tap[6] = -70.0 * (swa + swb) / d7; Tap[5] = 84.0 * (swa2 + 3.0*swa*swb + swb2) / d7; Tap[4] = -35.0 * (swa3 + 9.0*swa2*swb + 9.0*swa*swb2 + swb3 ) / d7; Tap[3] = 140.0 * (swa3*swb + 3.0*swa2*swb2 + swa*swb3 ) / d7; Tap[2] =-210.0 * (swa3*swb2 + swa2*swb3) / d7; Tap[1] = 140.0 * swa3 * swb3 / d7; Tap[0] = (-35.0*swa3*swb2*swb2 + 21.0*swa2*swb3*swb2 + 7.0*swa*swb3*swb3 + swb3*swb3*swb ) / d7; } /* ---------------------------------------------------------------------- */ void FixQEqReax::setup_pre_force(int vflag) { neighbor->build_one(list->index); deallocate_storage(); allocate_storage(); init_storage(); deallocate_matrix(); allocate_matrix(); pre_force(vflag); } /* ---------------------------------------------------------------------- */ void FixQEqReax::setup_pre_force_respa(int vflag, int ilevel) { if (ilevel < nlevels_respa-1) return; setup_pre_force(vflag); } /* ---------------------------------------------------------------------- */ void FixQEqReax::min_setup_pre_force(int vflag) { setup_pre_force(vflag); } /* ---------------------------------------------------------------------- */ void FixQEqReax::init_storage() { int NN; if (reaxc) NN = reaxc->list->inum + reaxc->list->gnum; else NN = list->inum + list->gnum; for( int i = 0; i < NN; i++ ) { Hdia_inv[i] = 1. / eta[atom->type[i]]; b_s[i] = -chi[atom->type[i]]; b_t[i] = -1.0; b_prc[i] = 0; b_prm[i] = 0; s[i] = t[i] = 0; } } /* ---------------------------------------------------------------------- */ void FixQEqReax::pre_force(int vflag) { double t_start, t_end; if (update->ntimestep % nevery) return; if( comm->me == 0 ) t_start = MPI_Wtime(); n = atom->nlocal; N = atom->nlocal + atom->nghost; // grow arrays if necessary // need to be atom->nmax in length if( atom->nmax > nmax ) reallocate_storage(); if( n > n_cap*DANGER_ZONE || m_fill > m_cap*DANGER_ZONE ) reallocate_matrix(); init_matvec(); matvecs = CG(b_s, s); // CG on s - parallel matvecs += CG(b_t, t); // CG on t - parallel calculate_Q(); if( comm->me == 0 ) { t_end = MPI_Wtime(); qeq_time = t_end - t_start; } } /* ---------------------------------------------------------------------- */ void FixQEqReax::pre_force_respa(int vflag, int ilevel, int iloop) { if (ilevel == nlevels_respa-1) pre_force(vflag); } /* ---------------------------------------------------------------------- */ void FixQEqReax::min_pre_force(int vflag) { pre_force(vflag); } /* ---------------------------------------------------------------------- */ void FixQEqReax::init_matvec() { /* fill-in H matrix */ compute_H(); int nn, ii, i; int *ilist; if (reaxc) { nn = reaxc->list->inum; ilist = reaxc->list->ilist; } else { nn = list->inum; ilist = list->ilist; } for( ii = 0; ii < nn; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) { /* init pre-conditioner for H and init solution vectors */ Hdia_inv[i] = 1. / eta[ atom->type[i] ]; b_s[i] = -chi[ atom->type[i] ]; b_t[i] = -1.0; /* linear extrapolation for s & t from previous solutions */ //s[i] = 2 * s_hist[i][0] - s_hist[i][1]; //t[i] = 2 * t_hist[i][0] - t_hist[i][1]; /* quadratic extrapolation for s & t from previous solutions */ //s[i] = s_hist[i][2] + 3 * ( s_hist[i][0] - s_hist[i][1] ); t[i] = t_hist[i][2] + 3 * ( t_hist[i][0] - t_hist[i][1] ); /* cubic extrapolation for s & t from previous solutions */ s[i] = 4*(s_hist[i][0]+s_hist[i][2])-(6*s_hist[i][1]+s_hist[i][3]); //t[i] = 4*(t_hist[i][0]+t_hist[i][2])-(6*t_hist[i][1]+t_hist[i][3]); } } pack_flag = 2; comm->forward_comm_fix(this); //Dist_vector( s ); pack_flag = 3; comm->forward_comm_fix(this); //Dist_vector( t ); } /* ---------------------------------------------------------------------- */ void FixQEqReax::compute_H() { int inum, jnum, *ilist, *jlist, *numneigh, **firstneigh; - int i, j, ii, jj, temp, newnbr, flag; + int i, j, ii, jj, flag; double **x, SMALL = 0.0001; double dx, dy, dz, r_sqr; int *type = atom->type; tagint *tag = atom->tag; x = atom->x; int *mask = atom->mask; if (reaxc) { inum = reaxc->list->inum; ilist = reaxc->list->ilist; numneigh = reaxc->list->numneigh; firstneigh = reaxc->list->firstneigh; } else { inum = list->inum; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; } // fill in the H matrix m_fill = 0; r_sqr = 0; for( ii = 0; ii < inum; ii++ ) { i = ilist[ii]; if (mask[i] & groupbit) { jlist = firstneigh[i]; jnum = numneigh[i]; H.firstnbr[i] = m_fill; for( jj = 0; jj < jnum; jj++ ) { j = jlist[jj]; dx = x[j][0] - x[i][0]; dy = x[j][1] - x[i][1]; dz = x[j][2] - x[i][2]; r_sqr = SQR(dx) + SQR(dy) + SQR(dz); flag = 0; if (r_sqr <= SQR(swb)) { if (j < n) flag = 1; else if (tag[i] < tag[j]) flag = 1; else if (tag[i] == tag[j]) { if (dz > SMALL) flag = 1; else if (fabs(dz) < SMALL) { if (dy > SMALL) flag = 1; else if (fabs(dy) < SMALL && dx > SMALL) flag = 1; } } } if( flag ) { H.jlist[m_fill] = j; H.val[m_fill] = calculate_H( sqrt(r_sqr), shld[type[i]][type[j]] ); m_fill++; } } H.numnbrs[i] = m_fill - H.firstnbr[i]; } } if (m_fill >= H.m) { char str[128]; sprintf(str,"H matrix size has been exceeded: m_fill=%d H.m=%d\n", m_fill, H.m ); error->warning(FLERR,str); error->all(FLERR,"Fix qeq/reax has insufficient QEq matrix size"); } } /* ---------------------------------------------------------------------- */ double FixQEqReax::calculate_H( double r, double gamma ) { double Taper, denom; Taper = Tap[7] * r + Tap[6]; Taper = Taper * r + Tap[5]; Taper = Taper * r + Tap[4]; Taper = Taper * r + Tap[3]; Taper = Taper * r + Tap[2]; Taper = Taper * r + Tap[1]; Taper = Taper * r + Tap[0]; denom = r * r * r + gamma; denom = pow(denom,0.3333333333333); return Taper * EV_TO_KCAL_PER_MOL / denom; } /* ---------------------------------------------------------------------- */ int FixQEqReax::CG( double *b, double *x ) { int i, j, imax; double tmp, alpha, beta, b_norm; - double sig_old, sig_new, sig0; + double sig_old, sig_new; int nn, jj; int *ilist; if (reaxc) { nn = reaxc->list->inum; ilist = reaxc->list->ilist; } else { nn = list->inum; ilist = list->ilist; } imax = 200; pack_flag = 1; sparse_matvec( &H, x, q ); comm->reverse_comm_fix( this ); //Coll_Vector( q ); vector_sum( r , 1., b, -1., q, nn ); for( jj = 0; jj < nn; ++jj ) { j = ilist[jj]; if (atom->mask[j] & groupbit) d[j] = r[j] * Hdia_inv[j]; //pre-condition } - int ttype = 1; b_norm = parallel_norm( b, nn ); sig_new = parallel_dot( r, d, nn); - sig0 = sig_new; for( i = 1; i < imax && sqrt(sig_new) / b_norm > tolerance; ++i ) { comm->forward_comm_fix(this); //Dist_vector( d ); sparse_matvec( &H, d, q ); comm->reverse_comm_fix(this); //Coll_vector( q ); - ttype = 2; tmp = parallel_dot( d, q, nn); alpha = sig_new / tmp; vector_add( x, alpha, d, nn ); vector_add( r, -alpha, q, nn ); // pre-conditioning for( jj = 0; jj < nn; ++jj ) { j = ilist[jj]; if (atom->mask[j] & groupbit) p[j] = r[j] * Hdia_inv[j]; } sig_old = sig_new; sig_new = parallel_dot( r, p, nn); beta = sig_new / sig_old; vector_sum( d, 1., p, beta, d, nn ); } if (i >= imax && comm->me == 0) { char str[128]; sprintf(str,"Fix qeq/reax CG convergence failed after %d iterations " "at " BIGINT_FORMAT " step",i,update->ntimestep); error->warning(FLERR,str); } return i; } /* ---------------------------------------------------------------------- */ void FixQEqReax::sparse_matvec( sparse_matrix *A, double *x, double *b ) { int i, j, itr_j; int nn, NN, ii; int *ilist; if (reaxc) { nn = reaxc->list->inum; NN = reaxc->list->inum + reaxc->list->gnum; ilist = reaxc->list->ilist; } else { nn = list->inum; NN = list->inum + list->gnum; ilist = list->ilist; } for( ii = 0; ii < nn; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) b[i] = eta[ atom->type[i] ] * x[i]; } for( ii = nn; ii < NN; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) b[i] = 0; } for( ii = 0; ii < nn; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) { for( itr_j=A->firstnbr[i]; itr_j<A->firstnbr[i]+A->numnbrs[i]; itr_j++) { j = A->jlist[itr_j]; b[i] += A->val[itr_j] * x[j]; b[j] += A->val[itr_j] * x[i]; } } } } /* ---------------------------------------------------------------------- */ void FixQEqReax::calculate_Q() { int i, k; double u, s_sum, t_sum; double *q = atom->q; int nn, ii; int *ilist; if (reaxc) { nn = reaxc->list->inum; ilist = reaxc->list->ilist; } else { nn = list->inum; ilist = list->ilist; } s_sum = parallel_vector_acc( s, nn ); t_sum = parallel_vector_acc( t, nn); u = s_sum / t_sum; for( ii = 0; ii < nn; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) { q[i] = s[i] - u * t[i]; /* backup s & t */ for( k = 4; k > 0; --k ) { s_hist[i][k] = s_hist[i][k-1]; t_hist[i][k] = t_hist[i][k-1]; } s_hist[i][0] = s[i]; t_hist[i][0] = t[i]; } } pack_flag = 4; comm->forward_comm_fix( this ); //Dist_vector( atom->q ); } /* ---------------------------------------------------------------------- */ int FixQEqReax::pack_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) { int m; if( pack_flag == 1) for(m = 0; m < n; m++) buf[m] = d[list[m]]; else if( pack_flag == 2 ) for(m = 0; m < n; m++) buf[m] = s[list[m]]; else if( pack_flag == 3 ) for(m = 0; m < n; m++) buf[m] = t[list[m]]; else if( pack_flag == 4 ) for(m = 0; m < n; m++) buf[m] = atom->q[list[m]]; return 1; } /* ---------------------------------------------------------------------- */ void FixQEqReax::unpack_comm(int n, int first, double *buf) { int i, m; if( pack_flag == 1) for(m = 0, i = first; m < n; m++, i++) d[i] = buf[m]; else if( pack_flag == 2) for(m = 0, i = first; m < n; m++, i++) s[i] = buf[m]; else if( pack_flag == 3) for(m = 0, i = first; m < n; m++, i++) t[i] = buf[m]; else if( pack_flag == 4) for(m = 0, i = first; m < n; m++, i++) atom->q[i] = buf[m]; } /* ---------------------------------------------------------------------- */ int FixQEqReax::pack_reverse_comm(int n, int first, double *buf) { int i, m; for(m = 0, i = first; m < n; m++, i++) buf[m] = q[i]; return 1; } /* ---------------------------------------------------------------------- */ void FixQEqReax::unpack_reverse_comm(int n, int *list, double *buf) { for(int m = 0; m < n; m++) q[list[m]] += buf[m]; } /* ---------------------------------------------------------------------- memory usage of local atom-based arrays ------------------------------------------------------------------------- */ double FixQEqReax::memory_usage() { double bytes; bytes = atom->nmax*nprev*2 * sizeof(double); // s_hist & t_hist bytes += atom->nmax*11 * sizeof(double); // storage bytes += n_cap*2 * sizeof(int); // matrix... bytes += m_cap * sizeof(int); bytes += m_cap * sizeof(double); return bytes; } /* ---------------------------------------------------------------------- allocate fictitious charge arrays ------------------------------------------------------------------------- */ void FixQEqReax::grow_arrays(int nmax) { memory->grow(s_hist,nmax,nprev,"qeq:s_hist"); memory->grow(t_hist,nmax,nprev,"qeq:t_hist"); } /* ---------------------------------------------------------------------- copy values within fictitious charge arrays ------------------------------------------------------------------------- */ void FixQEqReax::copy_arrays(int i, int j, int delflag) { for (int m = 0; m < nprev; m++) { s_hist[j][m] = s_hist[i][m]; t_hist[j][m] = t_hist[i][m]; } } /* ---------------------------------------------------------------------- pack values in local atom-based array for exchange with another proc ------------------------------------------------------------------------- */ int FixQEqReax::pack_exchange(int i, double *buf) { for (int m = 0; m < nprev; m++) buf[m] = s_hist[i][m]; for (int m = 0; m < nprev; m++) buf[nprev+m] = t_hist[i][m]; return nprev*2; } /* ---------------------------------------------------------------------- unpack values in local atom-based array from exchange with another proc ------------------------------------------------------------------------- */ int FixQEqReax::unpack_exchange(int nlocal, double *buf) { for (int m = 0; m < nprev; m++) s_hist[nlocal][m] = buf[m]; for (int m = 0; m < nprev; m++) t_hist[nlocal][m] = buf[nprev+m]; return nprev*2; } /* ---------------------------------------------------------------------- */ double FixQEqReax::parallel_norm( double *v, int n ) { int i; double my_sum, norm_sqr; int ii; int *ilist; if (reaxc) ilist = reaxc->list->ilist; else ilist = list->ilist; my_sum = 0.0; norm_sqr = 0.0; for( ii = 0; ii < n; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) my_sum += SQR( v[i] ); } MPI_Allreduce( &my_sum, &norm_sqr, 1, MPI_DOUBLE, MPI_SUM, world ); return sqrt( norm_sqr ); } /* ---------------------------------------------------------------------- */ double FixQEqReax::parallel_dot( double *v1, double *v2, int n) { int i; double my_dot, res; int ii; int *ilist; if (reaxc) ilist = reaxc->list->ilist; else ilist = list->ilist; my_dot = 0.0; res = 0.0; for( ii = 0; ii < n; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) my_dot += v1[i] * v2[i]; } MPI_Allreduce( &my_dot, &res, 1, MPI_DOUBLE, MPI_SUM, world ); return res; } /* ---------------------------------------------------------------------- */ double FixQEqReax::parallel_vector_acc( double *v, int n ) { int i; double my_acc, res; int ii; int *ilist; if (reaxc) ilist = reaxc->list->ilist; else ilist = list->ilist; my_acc = 0.0; res = 0.0; for( ii = 0; ii < n; ++ii ) { i = ilist[ii]; if (atom->mask[i] & groupbit) my_acc += v[i]; } MPI_Allreduce( &my_acc, &res, 1, MPI_DOUBLE, MPI_SUM, world ); return res; } /* ---------------------------------------------------------------------- */ void FixQEqReax::vector_sum( double* dest, double c, double* v, double d, double* y, int k ) { int kk; int *ilist; if (reaxc) ilist = reaxc->list->ilist; else ilist = list->ilist; for( --k; k>=0; --k ) { kk = ilist[k]; if (atom->mask[kk] & groupbit) dest[kk] = c * v[kk] + d * y[kk]; } } /* ---------------------------------------------------------------------- */ void FixQEqReax::vector_add( double* dest, double c, double* v, int k ) { int kk; int *ilist; if (reaxc) ilist = reaxc->list->ilist; else ilist = list->ilist; for( --k; k>=0; --k ) { kk = ilist[k]; if (atom->mask[kk] & groupbit) dest[kk] += c * v[kk]; } } diff --git a/src/USER-REAXC/pair_reax_c.cpp b/src/USER-REAXC/pair_reax_c.cpp index 47c9ea24a..cb8fa0be5 100644 --- a/src/USER-REAXC/pair_reax_c.cpp +++ b/src/USER-REAXC/pair_reax_c.cpp @@ -1,840 +1,824 @@ /* ---------------------------------------------------------------------- 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 author: Hasan Metin Aktulga, Purdue University (now at Lawrence Berkeley National Laboratory, hmaktulga@lbl.gov) Per-atom energy/virial added by Ray Shan (Sandia) Fix reax/c/bonds and fix reax/c/species for pair_style reax/c added by Ray Shan (Sandia) Hybrid and hybrid/overlay compatibility added by Ray Shan (Sandia) ------------------------------------------------------------------------- */ #include "pair_reax_c.h" #include "atom.h" #include "update.h" #include "force.h" #include "comm.h" #include "neighbor.h" #include "neigh_list.h" #include "neigh_request.h" #include "modify.h" #include "fix.h" #include "fix_reax_c.h" #include "citeme.h" #include "memory.h" #include "error.h" #include "reaxc_types.h" #include "reaxc_allocate.h" #include "reaxc_control.h" #include "reaxc_ffield.h" #include "reaxc_forces.h" #include "reaxc_init_md.h" #include "reaxc_io_tools.h" #include "reaxc_list.h" #include "reaxc_lookup.h" #include "reaxc_reset_tools.h" #include "reaxc_traj.h" #include "reaxc_vector.h" #include "fix_reaxc_bonds.h" using namespace LAMMPS_NS; static const char cite_pair_reax_c[] = "pair reax/c command:\n\n" "@Article{Aktulga12,\n" " author = {H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama},\n" " title = {Parallel reactive molecular dynamics: Numerical methods and algorithmic techniques},\n" " journal = {Parallel Computing},\n" " year = 2012,\n" " volume = 38,\n" " pages = {245--259}\n" "}\n\n"; /* ---------------------------------------------------------------------- */ PairReaxC::PairReaxC(LAMMPS *lmp) : Pair(lmp) { if (lmp->citeme) lmp->citeme->add(cite_pair_reax_c); single_enable = 0; restartinfo = 0; one_coeff = 1; manybody_flag = 1; ghostneigh = 1; system = (reax_system *) memory->smalloc(sizeof(reax_system),"reax:system"); control = (control_params *) memory->smalloc(sizeof(control_params),"reax:control"); data = (simulation_data *) memory->smalloc(sizeof(simulation_data),"reax:data"); workspace = (storage *) memory->smalloc(sizeof(storage),"reax:storage"); lists = (reax_list *) memory->smalloc(LIST_N * sizeof(reax_list),"reax:lists"); out_control = (output_controls *) memory->smalloc(sizeof(output_controls),"reax:out_control"); mpi_data = (mpi_datatypes *) memory->smalloc(sizeof(mpi_datatypes),"reax:mpi"); MPI_Comm_rank(world,&system->my_rank); system->my_coords[0] = 0; system->my_coords[1] = 0; system->my_coords[2] = 0; system->num_nbrs = 0; system->n = 0; // my atoms system->N = 0; // mine + ghosts system->bigN = 0; // all atoms in the system system->local_cap = 0; system->total_cap = 0; system->gcell_cap = 0; system->bndry_cuts.ghost_nonb = 0; system->bndry_cuts.ghost_hbond = 0; system->bndry_cuts.ghost_bond = 0; system->bndry_cuts.ghost_cutoff = 0; system->my_atoms = NULL; system->pair_ptr = this; fix_reax = NULL; tmpid = NULL; tmpbo = NULL; nextra = 14; pvector = new double[nextra]; setup_flag = 0; fixspecies_flag = 0; nmax = 0; } /* ---------------------------------------------------------------------- */ PairReaxC::~PairReaxC() { if (fix_reax) modify->delete_fix("REAXC"); if (setup_flag) { Close_Output_Files( system, control, out_control, mpi_data ); // deallocate reax data-structures if( control->tabulate ) Deallocate_Lookup_Tables( system ); if( control->hbond_cut > 0 ) Delete_List( lists+HBONDS, world ); Delete_List( lists+BONDS, world ); Delete_List( lists+THREE_BODIES, world ); Delete_List( lists+FAR_NBRS, world ); DeAllocate_Workspace( control, workspace ); DeAllocate_System( system ); } memory->destroy( system ); memory->destroy( control ); memory->destroy( data ); memory->destroy( workspace ); memory->destroy( lists ); memory->destroy( out_control ); memory->destroy( mpi_data ); // deallocate interface storage if( allocated ) { memory->destroy(setflag); memory->destroy(cutsq); memory->destroy(cutghost); delete [] map; delete [] chi; delete [] eta; delete [] gamma; } memory->destroy(tmpid); memory->destroy(tmpbo); delete [] pvector; } /* ---------------------------------------------------------------------- */ void PairReaxC::allocate( ) { allocated = 1; int n = atom->ntypes; memory->create(setflag,n+1,n+1,"pair:setflag"); memory->create(cutsq,n+1,n+1,"pair:cutsq"); memory->create(cutghost,n+1,n+1,"pair:cutghost"); map = new int[n+1]; chi = new double[n+1]; eta = new double[n+1]; gamma = new double[n+1]; } /* ---------------------------------------------------------------------- */ void PairReaxC::settings(int narg, char **arg) { if (narg < 1) error->all(FLERR,"Illegal pair_style command"); // read name of control file or use default controls if (strcmp(arg[0],"NULL") == 0) { strcpy( control->sim_name, "simulate" ); control->ensemble = 0; out_control->energy_update_freq = 0; control->tabulate = 0; control->reneighbor = 1; control->vlist_cut = control->nonb_cut; control->bond_cut = 5.; control->hbond_cut = 7.50; control->thb_cut = 0.001; control->thb_cutsq = 0.00001; control->bg_cut = 0.3; out_control->write_steps = 0; out_control->traj_method = 0; strcpy( out_control->traj_title, "default_title" ); out_control->atom_info = 0; out_control->bond_info = 0; out_control->angle_info = 0; } else Read_Control_File(arg[0], control, out_control); // default values qeqflag = 1; control->lgflag = 0; system->mincap = MIN_CAP; system->safezone = SAFE_ZONE; system->saferzone = SAFER_ZONE; // process optional keywords int iarg = 1; while (iarg < narg) { if (strcmp(arg[iarg],"checkqeq") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reax/c command"); if (strcmp(arg[iarg+1],"yes") == 0) qeqflag = 1; else if (strcmp(arg[iarg+1],"no") == 0) qeqflag = 0; else error->all(FLERR,"Illegal pair_style reax/c command"); iarg += 2; } else if (strcmp(arg[iarg],"lgvdw") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reax/c command"); if (strcmp(arg[iarg+1],"yes") == 0) control->lgflag = 1; else if (strcmp(arg[iarg+1],"no") == 0) control->lgflag = 0; else error->all(FLERR,"Illegal pair_style reax/c command"); iarg += 2; } else if (strcmp(arg[iarg],"safezone") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reax/c command"); system->safezone = force->numeric(FLERR,arg[iarg+1]); if (system->safezone < 0.0) error->all(FLERR,"Illegal pair_style reax/c safezone command"); system->saferzone = system->safezone + 0.2; iarg += 2; } else if (strcmp(arg[iarg],"mincap") == 0) { if (iarg+2 > narg) error->all(FLERR,"Illegal pair_style reax/c command"); system->mincap = force->inumeric(FLERR,arg[iarg+1]); if (system->mincap < 0) error->all(FLERR,"Illegal pair_style reax/c mincap command"); iarg += 2; } else error->all(FLERR,"Illegal pair_style reax/c command"); } // LAMMPS is responsible for generating nbrs control->reneighbor = 1; } /* ---------------------------------------------------------------------- */ void PairReaxC::coeff( int nargs, char **args ) { if (!allocated) allocate(); if (nargs != 3 + atom->ntypes) error->all(FLERR,"Incorrect args for pair coefficients"); // insure I,J args are * * if (strcmp(args[0],"*") != 0 || strcmp(args[1],"*") != 0) error->all(FLERR,"Incorrect args for pair coefficients"); // read ffield file Read_Force_Field(args[2], &(system->reax_param), control); // read args that map atom types to elements in potential file // map[i] = which element the Ith atom type is, -1 if NULL int itmp = 0; int nreax_types = system->reax_param.num_atom_types; for (int i = 3; i < nargs; i++) { if (strcmp(args[i],"NULL") == 0) { map[i-2] = -1; itmp ++; continue; } } int n = atom->ntypes; // pair_coeff element map for (int i = 3; i < nargs; i++) for (int j = 0; j < nreax_types; j++) if (strcasecmp(args[i],system->reax_param.sbp[j].name) == 0) { map[i-2] = j; itmp ++; } // error check if (itmp != n) error->all(FLERR,"Non-existent ReaxFF type"); for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) setflag[i][j] = 0; // set setflag i,j for type pairs where both are mapped to elements int count = 0; for (int i = 1; i <= n; i++) for (int j = i; j <= n; j++) if (map[i] >= 0 && map[j] >= 0) { setflag[i][j] = 1; count++; } if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } /* ---------------------------------------------------------------------- */ void PairReaxC::init_style( ) { if (!atom->q_flag) error->all(FLERR,"Pair reax/c requires atom attribute q"); // firstwarn = 1; int iqeq; for (iqeq = 0; iqeq < modify->nfix; iqeq++) if (strcmp(modify->fix[iqeq]->style,"qeq/reax") == 0) break; if (iqeq == modify->nfix && qeqflag == 1) error->all(FLERR,"Pair reax/c requires use of fix qeq/reax"); system->n = atom->nlocal; // my atoms system->N = atom->nlocal + atom->nghost; // mine + ghosts system->bigN = static_cast<int> (atom->natoms); // all atoms in the system system->wsize = comm->nprocs; system->big_box.V = 0; system->big_box.box_norms[0] = 0; system->big_box.box_norms[1] = 0; system->big_box.box_norms[2] = 0; if (atom->tag_enable == 0) error->all(FLERR,"Pair style reax/c requires atom IDs"); if (force->newton_pair == 0) error->all(FLERR,"Pair style reax/c requires newton pair on"); // need a half neighbor list w/ Newton off and ghost neighbors // built whenever re-neighboring occurs int irequest = neighbor->request(this); neighbor->requests[irequest]->newton = 2; neighbor->requests[irequest]->ghost = 1; cutmax = MAX3(control->nonb_cut, control->hbond_cut, 2*control->bond_cut); for( int i = 0; i < LIST_N; ++i ) lists[i].allocated = 0; if (fix_reax == NULL) { char **fixarg = new char*[3]; fixarg[0] = (char *) "REAXC"; fixarg[1] = (char *) "all"; fixarg[2] = (char *) "REAXC"; modify->add_fix(3,fixarg); delete [] fixarg; fix_reax = (FixReaxC *) modify->fix[modify->nfix-1]; } } /* ---------------------------------------------------------------------- */ void PairReaxC::setup( ) { int oldN; int mincap = system->mincap; double safezone = system->safezone; system->n = atom->nlocal; // my atoms system->N = atom->nlocal + atom->nghost; // mine + ghosts oldN = system->N; system->bigN = static_cast<int> (atom->natoms); // all atoms in the system if (setup_flag == 0) { setup_flag = 1; int *num_bonds = fix_reax->num_bonds; int *num_hbonds = fix_reax->num_hbonds; control->vlist_cut = neighbor->cutneighmax; // determine the local and total capacity system->local_cap = MAX( (int)(system->n * safezone), mincap ); system->total_cap = MAX( (int)(system->N * safezone), mincap ); // initialize my data structures PreAllocate_Space( system, control, workspace, world ); write_reax_atoms(); int num_nbrs = estimate_reax_lists(); if(!Make_List(system->total_cap, num_nbrs, TYP_FAR_NEIGHBOR, lists+FAR_NBRS, world)) error->all(FLERR,"Pair reax/c problem in far neighbor list"); write_reax_lists(); Initialize( system, control, data, workspace, &lists, out_control, mpi_data, world ); for( int k = 0; k < system->N; ++k ) { num_bonds[k] = system->my_atoms[k].num_bonds; num_hbonds[k] = system->my_atoms[k].num_hbonds; } } else { // fill in reax datastructures write_reax_atoms(); // reset the bond list info for new atoms for(int k = oldN; k < system->N; ++k) Set_End_Index( k, Start_Index( k, lists+BONDS ), lists+BONDS ); // check if I need to shrink/extend my data-structs ReAllocate( system, control, data, workspace, &lists, mpi_data ); } ngroup = 0; int ngroup_sum = 0; for (int i = 0; i < list->inum; i++) { ngroup ++; } MPI_Allreduce( &ngroup, &ngroup_sum, 1, MPI_INT, MPI_SUM, world ); ngroup = ngroup_sum; } /* ---------------------------------------------------------------------- */ double PairReaxC::init_one(int i, int j) { if (setflag[i][j] == 0) error->all(FLERR,"All pair coeffs are not set"); cutghost[i][j] = cutghost[j][i] = cutmax; return cutmax; } /* ---------------------------------------------------------------------- */ void PairReaxC::compute(int eflag, int vflag) { double evdwl,ecoul; double t_start, t_end; // communicate num_bonds once every reneighboring // 2 num arrays stored by fix, grab ptr to them if (neighbor->ago == 0) comm->forward_comm_fix(fix_reax); int *num_bonds = fix_reax->num_bonds; int *num_hbonds = fix_reax->num_hbonds; evdwl = ecoul = 0.0; if (eflag || vflag) ev_setup(eflag,vflag); else ev_unset(); if (vflag_global) control->virial = 1; else control->virial = 0; system->n = atom->nlocal; // my atoms system->N = atom->nlocal + atom->nghost; // mine + ghosts system->bigN = static_cast<int> (atom->natoms); // all atoms in the system system->big_box.V = 0; system->big_box.box_norms[0] = 0; system->big_box.box_norms[1] = 0; system->big_box.box_norms[2] = 0; if( comm->me == 0 ) t_start = MPI_Wtime(); // setup data structures setup(); Reset( system, control, data, workspace, &lists, world ); workspace->realloc.num_far = write_reax_lists(); // timing for filling in the reax lists if( comm->me == 0 ) { t_end = MPI_Wtime(); data->timing.nbrs = t_end - t_start; } // forces Compute_Forces(system,control,data,workspace,&lists,out_control,mpi_data); read_reax_forces(vflag); for(int k = 0; k < system->N; ++k) { num_bonds[k] = system->my_atoms[k].num_bonds; num_hbonds[k] = system->my_atoms[k].num_hbonds; } // energies and pressure if (eflag_global) { evdwl += data->my_en.e_bond; evdwl += data->my_en.e_ov; evdwl += data->my_en.e_un; evdwl += data->my_en.e_lp; evdwl += data->my_en.e_ang; evdwl += data->my_en.e_pen; evdwl += data->my_en.e_coa; evdwl += data->my_en.e_hb; evdwl += data->my_en.e_tor; evdwl += data->my_en.e_con; evdwl += data->my_en.e_vdW; ecoul += data->my_en.e_ele; ecoul += data->my_en.e_pol; // eng_vdwl += evdwl; // eng_coul += ecoul; // Store the different parts of the energy // in a list for output by compute pair command pvector[0] = data->my_en.e_bond; pvector[1] = data->my_en.e_ov + data->my_en.e_un; pvector[2] = data->my_en.e_lp; pvector[3] = 0.0; pvector[4] = data->my_en.e_ang; pvector[5] = data->my_en.e_pen; pvector[6] = data->my_en.e_coa; pvector[7] = data->my_en.e_hb; pvector[8] = data->my_en.e_tor; pvector[9] = data->my_en.e_con; pvector[10] = data->my_en.e_vdW; pvector[11] = data->my_en.e_ele; pvector[12] = 0.0; pvector[13] = data->my_en.e_pol; } if (vflag_fdotr) virial_fdotr_compute(); // Set internal timestep counter to that of LAMMPS data->step = update->ntimestep; Output_Results( system, control, data, &lists, out_control, mpi_data ); // populate tmpid and tmpbo arrays for fix reax/c/species int i, j; if(fixspecies_flag) { if (system->N > nmax) { memory->destroy(tmpid); memory->destroy(tmpbo); nmax = system->N; memory->create(tmpid,nmax,MAXSPECBOND,"pair:tmpid"); memory->create(tmpbo,nmax,MAXSPECBOND,"pair:tmpbo"); } for (i = 0; i < system->N; i ++) for (j = 0; j < MAXSPECBOND; j ++) { tmpbo[i][j] = 0.0; tmpid[i][j] = 0; } FindBond(); } } /* ---------------------------------------------------------------------- */ void PairReaxC::write_reax_atoms() { int *num_bonds = fix_reax->num_bonds; int *num_hbonds = fix_reax->num_hbonds; if (system->N > system->total_cap) error->all(FLERR,"Too many ghost atoms"); for( int i = 0; i < system->N; ++i ){ system->my_atoms[i].orig_id = atom->tag[i]; system->my_atoms[i].type = map[atom->type[i]]; system->my_atoms[i].x[0] = atom->x[i][0]; system->my_atoms[i].x[1] = atom->x[i][1]; system->my_atoms[i].x[2] = atom->x[i][2]; system->my_atoms[i].q = atom->q[i]; system->my_atoms[i].num_bonds = num_bonds[i]; system->my_atoms[i].num_hbonds = num_hbonds[i]; } } /* ---------------------------------------------------------------------- */ void PairReaxC::get_distance( rvec xj, rvec xi, double *d_sqr, rvec *dvec ) { (*dvec)[0] = xj[0] - xi[0]; (*dvec)[1] = xj[1] - xi[1]; (*dvec)[2] = xj[2] - xi[2]; *d_sqr = SQR((*dvec)[0]) + SQR((*dvec)[1]) + SQR((*dvec)[2]); } /* ---------------------------------------------------------------------- */ void PairReaxC::set_far_nbr( far_neighbor_data *fdest, int j, double d, rvec dvec ) { fdest->nbr = j; fdest->d = d; rvec_Copy( fdest->dvec, dvec ); ivec_MakeZero( fdest->rel_box ); } /* ---------------------------------------------------------------------- */ int PairReaxC::estimate_reax_lists() { - int itr_i, itr_j, itr_g, i, j, g; - int nlocal, nghost, num_nbrs, num_marked; + int itr_i, itr_j, i, j; + int num_nbrs, num_marked; int *ilist, *jlist, *numneigh, **firstneigh, *marked; - double d_sqr, g_d_sqr; - rvec dvec, g_dvec; + double d_sqr; + rvec dvec; double **x; - reax_list *far_nbrs; - far_neighbor_data *far_list; int mincap = system->mincap; double safezone = system->safezone; x = atom->x; - nlocal = atom->nlocal; - nghost = atom->nghost; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; - far_nbrs = lists + FAR_NBRS; - far_list = far_nbrs->select.far_nbr_list; - num_nbrs = 0; num_marked = 0; marked = (int*) calloc( system->N, sizeof(int) ); - int inum = list->inum; - int gnum = list->gnum; - int numall = inum + gnum; + int numall = list->inum + list->gnum; - for( itr_i = 0; itr_i < inum+gnum; ++itr_i ){ + for( itr_i = 0; itr_i < numall; ++itr_i ){ i = ilist[itr_i]; marked[i] = 1; ++num_marked; jlist = firstneigh[i]; for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){ j = jlist[itr_j]; j &= NEIGHMASK; get_distance( x[j], x[i], &d_sqr, &dvec ); if( d_sqr <= SQR(control->nonb_cut) ) ++num_nbrs; } } free( marked ); return static_cast<int> (MAX( num_nbrs*safezone, mincap*MIN_NBRS )); } /* ---------------------------------------------------------------------- */ int PairReaxC::write_reax_lists() { - int itr_i, itr_j, itr_g, i, j, g, flag; - int nlocal, nghost, num_nbrs; + int itr_i, itr_j, i, j; + int num_nbrs; int *ilist, *jlist, *numneigh, **firstneigh; - double d_sqr, g_d, g_d_sqr; - rvec dvec, g_dvec; - double *dist, **x, SMALL = 0.0001; + double d_sqr; + rvec dvec; + double *dist, **x; reax_list *far_nbrs; far_neighbor_data *far_list; x = atom->x; - nlocal = atom->nlocal; - nghost = atom->nghost; ilist = list->ilist; numneigh = list->numneigh; firstneigh = list->firstneigh; far_nbrs = lists + FAR_NBRS; far_list = far_nbrs->select.far_nbr_list; num_nbrs = 0; dist = (double*) calloc( system->N, sizeof(double) ); - int inum = list->inum; - int gnum = list->gnum; - int numall = inum + gnum; + int numall = list->inum + list->gnum; - for( itr_i = 0; itr_i < inum+gnum; ++itr_i ){ + for( itr_i = 0; itr_i < numall; ++itr_i ){ i = ilist[itr_i]; jlist = firstneigh[i]; Set_Start_Index( i, num_nbrs, far_nbrs ); for( itr_j = 0; itr_j < numneigh[i]; ++itr_j ){ j = jlist[itr_j]; j &= NEIGHMASK; get_distance( x[j], x[i], &d_sqr, &dvec ); if( d_sqr <= (control->nonb_cut*control->nonb_cut) ){ dist[j] = sqrt( d_sqr ); set_far_nbr( &far_list[num_nbrs], j, dist[j], dvec ); ++num_nbrs; } } Set_End_Index( i, num_nbrs, far_nbrs ); } free( dist ); return num_nbrs; } /* ---------------------------------------------------------------------- */ void PairReaxC::read_reax_forces(int vflag) { for( int i = 0; i < system->N; ++i ) { system->my_atoms[i].f[0] = workspace->f[i][0]; system->my_atoms[i].f[1] = workspace->f[i][1]; system->my_atoms[i].f[2] = workspace->f[i][2]; atom->f[i][0] += -workspace->f[i][0]; atom->f[i][1] += -workspace->f[i][1]; atom->f[i][2] += -workspace->f[i][2]; } } /* ---------------------------------------------------------------------- */ void *PairReaxC::extract(const char *str, int &dim) { dim = 1; if (strcmp(str,"chi") == 0 && chi) { for (int i = 1; i <= atom->ntypes; i++) if (map[i] >= 0) chi[i] = system->reax_param.sbp[map[i]].chi; else chi[i] = 0.0; return (void *) chi; } if (strcmp(str,"eta") == 0 && eta) { for (int i = 1; i <= atom->ntypes; i++) if (map[i] >= 0) eta[i] = system->reax_param.sbp[map[i]].eta; else eta[i] = 0.0; return (void *) eta; } if (strcmp(str,"gamma") == 0 && gamma) { for (int i = 1; i <= atom->ntypes; i++) if (map[i] >= 0) gamma[i] = system->reax_param.sbp[map[i]].gamma; else gamma[i] = 0.0; return (void *) gamma; } return NULL; } /* ---------------------------------------------------------------------- */ double PairReaxC::memory_usage() { double bytes = 0.0; // From pair_reax_c bytes += 1.0 * system->N * sizeof(int); bytes += 1.0 * system->N * sizeof(double); // From reaxc_allocate: BO bytes += 1.0 * system->total_cap * sizeof(reax_atom); bytes += 19.0 * system->total_cap * sizeof(real); bytes += 3.0 * system->total_cap * sizeof(int); - double mem1 = bytes; - // From reaxc_lists bytes += 2.0 * lists->n * sizeof(int); bytes += lists->num_intrs * sizeof(three_body_interaction_data); bytes += lists->num_intrs * sizeof(bond_data); bytes += lists->num_intrs * sizeof(dbond_data); bytes += lists->num_intrs * sizeof(dDelta_data); bytes += lists->num_intrs * sizeof(far_neighbor_data); bytes += lists->num_intrs * sizeof(hbond_data); if(fixspecies_flag) bytes += 2 * nmax * MAXSPECBOND * sizeof(double); return bytes; } /* ---------------------------------------------------------------------- */ void PairReaxC::FindBond() { - int i, ii, j, pj, nj, jtmp, jj; - double bo_tmp, bo_cut, rij, rsq, r_tmp; + int i, j, pj, nj; + double bo_tmp, bo_cut; bond_data *bo_ij; bo_cut = 0.10; for (i = 0; i < system->n; i++) { nj = 0; for( pj = Start_Index(i, lists); pj < End_Index(i, lists); ++pj ) { bo_ij = &( lists->select.bond_list[pj] ); j = bo_ij->nbr; if (j < i) continue; bo_tmp = bo_ij->bo_data.BO; - r_tmp = bo_ij->d; if (bo_tmp >= bo_cut ) { tmpid[i][nj] = j; tmpbo[i][nj] = bo_tmp; nj ++; if (nj > MAXSPECBOND) error->all(FLERR,"Increase MAXSPECBOND in reaxc_defs.h"); } } } } diff --git a/src/USER-REAXC/reaxc_allocate.cpp b/src/USER-REAXC/reaxc_allocate.cpp index 1bf3d8575..474b60d06 100644 --- a/src/USER-REAXC/reaxc_allocate.cpp +++ b/src/USER-REAXC/reaxc_allocate.cpp @@ -1,697 +1,461 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_allocate.h" #include "reaxc_list.h" #include "reaxc_reset_tools.h" #include "reaxc_tool_box.h" #include "reaxc_vector.h" /* allocate space for my_atoms important: we cannot know the exact number of atoms that will fall into a process's box throughout the whole simulation. therefore we need to make upper bound estimates for various data structures */ int PreAllocate_Space( reax_system *system, control_params *control, storage *workspace, MPI_Comm comm ) { int mincap = system->mincap; double safezone = system->safezone; // determine the local and total capacity system->local_cap = MAX( (int)(system->n * safezone), mincap ); system->total_cap = MAX( (int)(system->N * safezone), mincap ); system->my_atoms = (reax_atom*) scalloc( system->total_cap, sizeof(reax_atom), "my_atoms", comm ); return SUCCESS; } /************* system *************/ -inline void reax_atom_Copy( reax_atom *dest, reax_atom *src ) -{ - dest->orig_id = src->orig_id; - dest->type = src->type; - strcpy( dest->name, src->name ); - rvec_Copy( dest->x, src->x ); - rvec_Copy( dest->v, src->v ); - rvec_Copy( dest->f_old, src->f_old ); - rvec_Copy( dest->s, src->s ); - rvec_Copy( dest->t, src->t ); - dest->Hindex = src->Hindex; - dest->num_bonds = src->num_bonds; - dest->num_hbonds = src->num_hbonds; - dest->numbonds = src->numbonds; -} - - -void Copy_Atom_List( reax_atom *dest, reax_atom *src, int n ) -{ - int i; - - for( i = 0; i < n; ++i ) - memcpy( dest+i, src+i, sizeof(reax_atom) ); -} - int Allocate_System( reax_system *system, int local_cap, int total_cap, char *msg ) { system->my_atoms = (reax_atom*) realloc( system->my_atoms, total_cap*sizeof(reax_atom) ); return SUCCESS; } void DeAllocate_System( reax_system *system ) { int i, j, k; int ntypes; reax_interaction *ff_params; // dealloocate the atom list sfree( system->my_atoms, "system->my_atoms" ); // deallocate the ffield parameters storage ff_params = &(system->reax_param); ntypes = ff_params->num_atom_types; sfree( ff_params->gp.l, "ff:globals" ); for( i = 0; i < ntypes; ++i ) { for( j = 0; j < ntypes; ++j ) { for( k = 0; k < ntypes; ++k ) { sfree( ff_params->fbp[i][j][k], "ff:fbp[i,j,k]" ); } sfree( ff_params->fbp[i][j], "ff:fbp[i,j]" ); sfree( ff_params->thbp[i][j], "ff:thbp[i,j]" ); sfree( ff_params->hbp[i][j], "ff:hbp[i,j]" ); } sfree( ff_params->fbp[i], "ff:fbp[i]" ); sfree( ff_params->thbp[i], "ff:thbp[i]" ); sfree( ff_params->hbp[i], "ff:hbp[i]" ); sfree( ff_params->tbp[i], "ff:tbp[i]" ); } sfree( ff_params->fbp, "ff:fbp" ); sfree( ff_params->thbp, "ff:thbp" ); sfree( ff_params->hbp, "ff:hbp" ); sfree( ff_params->tbp, "ff:tbp" ); sfree( ff_params->sbp, "ff:sbp" ); } /************* workspace *************/ void DeAllocate_Workspace( control_params *control, storage *workspace ) { int i; if( !workspace->allocated ) return; workspace->allocated = 0; /* communication storage */ for( i = 0; i < MAX_NBRS; ++i ) { sfree( workspace->tmp_dbl[i], "tmp_dbl[i]" ); sfree( workspace->tmp_rvec[i], "tmp_rvec[i]" ); sfree( workspace->tmp_rvec2[i], "tmp_rvec2[i]" ); } /* bond order storage */ sfree( workspace->within_bond_box, "skin" ); sfree( workspace->total_bond_order, "total_bo" ); sfree( workspace->Deltap, "Deltap" ); sfree( workspace->Deltap_boc, "Deltap_boc" ); sfree( workspace->dDeltap_self, "dDeltap_self" ); sfree( workspace->Delta, "Delta" ); sfree( workspace->Delta_lp, "Delta_lp" ); sfree( workspace->Delta_lp_temp, "Delta_lp_temp" ); sfree( workspace->dDelta_lp, "dDelta_lp" ); sfree( workspace->dDelta_lp_temp, "dDelta_lp_temp" ); sfree( workspace->Delta_e, "Delta_e" ); sfree( workspace->Delta_boc, "Delta_boc" ); sfree( workspace->Delta_val, "Delta_val" ); sfree( workspace->nlp, "nlp" ); sfree( workspace->nlp_temp, "nlp_temp" ); sfree( workspace->Clp, "Clp" ); sfree( workspace->vlpex, "vlpex" ); sfree( workspace->bond_mark, "bond_mark" ); sfree( workspace->done_after, "done_after" ); /* QEq storage */ sfree( workspace->Hdia_inv, "Hdia_inv" ); sfree( workspace->b_s, "b_s" ); sfree( workspace->b_t, "b_t" ); sfree( workspace->b_prc, "b_prc" ); sfree( workspace->b_prm, "b_prm" ); sfree( workspace->s, "s" ); sfree( workspace->t, "t" ); sfree( workspace->droptol, "droptol" ); sfree( workspace->b, "b" ); sfree( workspace->x, "x" ); /* GMRES storage */ for( i = 0; i < RESTART+1; ++i ) { sfree( workspace->h[i], "h[i]" ); sfree( workspace->v[i], "v[i]" ); } sfree( workspace->h, "h" ); sfree( workspace->v, "v" ); sfree( workspace->y, "y" ); sfree( workspace->z, "z" ); sfree( workspace->g, "g" ); sfree( workspace->hs, "hs" ); sfree( workspace->hc, "hc" ); /* CG storage */ sfree( workspace->r, "r" ); sfree( workspace->d, "d" ); sfree( workspace->q, "q" ); sfree( workspace->p, "p" ); sfree( workspace->r2, "r2" ); sfree( workspace->d2, "d2" ); sfree( workspace->q2, "q2" ); sfree( workspace->p2, "p2" ); /* integrator */ sfree( workspace->v_const, "v_const" ); /* force related storage */ sfree( workspace->f, "f" ); sfree( workspace->CdDelta, "CdDelta" ); } int Allocate_Workspace( reax_system *system, control_params *control, storage *workspace, int local_cap, int total_cap, MPI_Comm comm, char *msg ) { int i, total_real, total_rvec, local_rvec; workspace->allocated = 1; total_real = total_cap * sizeof(real); total_rvec = total_cap * sizeof(rvec); local_rvec = local_cap * sizeof(rvec); /* communication storage */ for( i = 0; i < MAX_NBRS; ++i ) { workspace->tmp_dbl[i] = (real*) scalloc( total_cap, sizeof(real), "tmp_dbl", comm ); workspace->tmp_rvec[i] = (rvec*) scalloc( total_cap, sizeof(rvec), "tmp_rvec", comm ); workspace->tmp_rvec2[i] = (rvec2*) scalloc( total_cap, sizeof(rvec2), "tmp_rvec2", comm ); } /* bond order related storage */ workspace->within_bond_box = (int*) scalloc( total_cap, sizeof(int), "skin", comm ); workspace->total_bond_order = (real*) smalloc( total_real, "total_bo", comm ); workspace->Deltap = (real*) smalloc( total_real, "Deltap", comm ); workspace->Deltap_boc = (real*) smalloc( total_real, "Deltap_boc", comm ); workspace->dDeltap_self = (rvec*) smalloc( total_rvec, "dDeltap_self", comm ); workspace->Delta = (real*) smalloc( total_real, "Delta", comm ); workspace->Delta_lp = (real*) smalloc( total_real, "Delta_lp", comm ); workspace->Delta_lp_temp = (real*) smalloc( total_real, "Delta_lp_temp", comm ); workspace->dDelta_lp = (real*) smalloc( total_real, "dDelta_lp", comm ); workspace->dDelta_lp_temp = (real*) smalloc( total_real, "dDelta_lp_temp", comm ); workspace->Delta_e = (real*) smalloc( total_real, "Delta_e", comm ); workspace->Delta_boc = (real*) smalloc( total_real, "Delta_boc", comm ); workspace->Delta_val = (real*) smalloc( total_real, "Delta_val", comm ); workspace->nlp = (real*) smalloc( total_real, "nlp", comm ); workspace->nlp_temp = (real*) smalloc( total_real, "nlp_temp", comm ); workspace->Clp = (real*) smalloc( total_real, "Clp", comm ); workspace->vlpex = (real*) smalloc( total_real, "vlpex", comm ); workspace->bond_mark = (int*) scalloc( total_cap, sizeof(int), "bond_mark", comm ); workspace->done_after = (int*) scalloc( total_cap, sizeof(int), "done_after", comm ); /* QEq storage */ workspace->Hdia_inv = (real*) scalloc( total_cap, sizeof(real), "Hdia_inv", comm ); workspace->b_s = (real*) scalloc( total_cap, sizeof(real), "b_s", comm ); workspace->b_t = (real*) scalloc( total_cap, sizeof(real), "b_t", comm ); workspace->b_prc = (real*) scalloc( total_cap, sizeof(real), "b_prc", comm ); workspace->b_prm = (real*) scalloc( total_cap, sizeof(real), "b_prm", comm ); workspace->s = (real*) scalloc( total_cap, sizeof(real), "s", comm ); workspace->t = (real*) scalloc( total_cap, sizeof(real), "t", comm ); workspace->droptol = (real*) scalloc( total_cap, sizeof(real), "droptol", comm ); workspace->b = (rvec2*) scalloc( total_cap, sizeof(rvec2), "b", comm ); workspace->x = (rvec2*) scalloc( total_cap, sizeof(rvec2), "x", comm ); /* GMRES storage */ workspace->y = (real*) scalloc( RESTART+1, sizeof(real), "y", comm ); workspace->z = (real*) scalloc( RESTART+1, sizeof(real), "z", comm ); workspace->g = (real*) scalloc( RESTART+1, sizeof(real), "g", comm ); workspace->h = (real**) scalloc( RESTART+1, sizeof(real*), "h", comm ); workspace->hs = (real*) scalloc( RESTART+1, sizeof(real), "hs", comm ); workspace->hc = (real*) scalloc( RESTART+1, sizeof(real), "hc", comm ); workspace->v = (real**) scalloc( RESTART+1, sizeof(real*), "v", comm ); for( i = 0; i < RESTART+1; ++i ) { workspace->h[i] = (real*) scalloc( RESTART+1, sizeof(real), "h[i]", comm ); workspace->v[i] = (real*) scalloc( total_cap, sizeof(real), "v[i]", comm ); } /* CG storage */ workspace->r = (real*) scalloc( total_cap, sizeof(real), "r", comm ); workspace->d = (real*) scalloc( total_cap, sizeof(real), "d", comm ); workspace->q = (real*) scalloc( total_cap, sizeof(real), "q", comm ); workspace->p = (real*) scalloc( total_cap, sizeof(real), "p", comm ); workspace->r2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "r2", comm ); workspace->d2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "d2", comm ); workspace->q2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "q2", comm ); workspace->p2 = (rvec2*) scalloc( total_cap, sizeof(rvec2), "p2", comm ); /* integrator storage */ workspace->v_const = (rvec*) smalloc( local_rvec, "v_const", comm ); // /* force related storage */ workspace->f = (rvec*) scalloc( total_cap, sizeof(rvec), "f", comm ); workspace->CdDelta = (real*) scalloc( total_cap, sizeof(real), "CdDelta", comm ); return SUCCESS; } -void Reallocate_Neighbor_List( reax_list *far_nbrs, int n, int num_intrs, - MPI_Comm comm ) +static void Reallocate_Neighbor_List( reax_list *far_nbrs, int n, + int num_intrs, MPI_Comm comm ) { Delete_List( far_nbrs, comm ); if(!Make_List( n, num_intrs, TYP_FAR_NEIGHBOR, far_nbrs, comm )){ fprintf(stderr, "Problem in initializing far nbrs list. Terminating!\n"); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } } -int Allocate_Matrix( sparse_matrix **pH, int cap, int m, MPI_Comm comm ) -{ - sparse_matrix *H; - - *pH = (sparse_matrix*) - smalloc( sizeof(sparse_matrix), "sparse_matrix", comm ); - H = *pH; - H->cap = cap; - H->m = m; - H->start = (int*) smalloc( sizeof(int) * cap, "matrix_start", comm ); - H->end = (int*) smalloc( sizeof(int) * cap, "matrix_end", comm ); - H->entries = (sparse_matrix_entry*) - smalloc( sizeof(sparse_matrix_entry)*m, "matrix_entries", comm ); - - return SUCCESS; -} - - -void Deallocate_Matrix( sparse_matrix *H ) -{ - sfree(H->start, "H->start"); - sfree(H->end, "H->end"); - sfree(H->entries, "H->entries"); - sfree(H, "H"); -} - - -int Reallocate_Matrix( sparse_matrix **H, int n, int m, char *name, - MPI_Comm comm ) -{ - Deallocate_Matrix( *H ); - if( !Allocate_Matrix( H, n, m, comm ) ) { - fprintf(stderr, "not enough space for %s matrix. terminating!\n", name); - MPI_Abort( comm, INSUFFICIENT_MEMORY ); - } - - return SUCCESS; -} - - -int Reallocate_HBonds_List( reax_system *system, reax_list *hbonds, - MPI_Comm comm ) +static int Reallocate_HBonds_List( reax_system *system, reax_list *hbonds, + MPI_Comm comm ) { int i, id, total_hbonds; int mincap = system->mincap; double saferzone = system->saferzone; total_hbonds = 0; for( i = 0; i < system->n; ++i ) if( (id = system->my_atoms[i].Hindex) >= 0 ) { total_hbonds += system->my_atoms[i].num_hbonds; } total_hbonds = (int)(MAX( total_hbonds*saferzone, mincap*MIN_HBONDS )); Delete_List( hbonds, comm ); if( !Make_List( system->Hcap, total_hbonds, TYP_HBOND, hbonds, comm ) ) { fprintf( stderr, "not enough space for hbonds list. terminating!\n" ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } return total_hbonds; } -int Reallocate_Bonds_List( reax_system *system, reax_list *bonds, - int *total_bonds, int *est_3body, MPI_Comm comm ) +static int Reallocate_Bonds_List( reax_system *system, reax_list *bonds, + int *total_bonds, int *est_3body, + MPI_Comm comm ) { int i; int mincap = system->mincap; double safezone = system->safezone; *total_bonds = 0; *est_3body = 0; for( i = 0; i < system->N; ++i ){ *est_3body += SQR(system->my_atoms[i].num_bonds); *total_bonds += system->my_atoms[i].num_bonds; } *total_bonds = (int)(MAX( *total_bonds * safezone, mincap*MIN_BONDS )); Delete_List( bonds, comm ); if(!Make_List(system->total_cap, *total_bonds, TYP_BOND, bonds, comm)) { fprintf( stderr, "not enough space for bonds list. terminating!\n" ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } return SUCCESS; } -/************* grid *************/ -int Estimate_GCell_Population( reax_system* system, MPI_Comm comm ) -{ - int d, i, j, k, l, max_atoms, my_max, all_max; - ivec c; - grid *g; - grid_cell *gc; - simulation_box *my_ext_box; - reax_atom *atoms; - - my_ext_box = &(system->my_ext_box); - g = &(system->my_grid); - atoms = system->my_atoms; - Reset_Grid( g ); - - for( l = 0; l < system->n; l++ ) { - for( d = 0; d < 3; ++d ) { - - c[d] = (int)((atoms[l].x[d]-my_ext_box->min[d])*g->inv_len[d]); - - if( c[d] >= g->native_end[d] ) - c[d] = g->native_end[d] - 1; - else if( c[d] < g->native_str[d] ) - c[d] = g->native_str[d]; - } - gc = &( g->cells[c[0]][c[1]][c[2]] ); - gc->top++; - } - - max_atoms = 0; - for( i = 0; i < g->ncells[0]; i++ ) - for( j = 0; j < g->ncells[1]; j++ ) - for( k = 0; k < g->ncells[2]; k++ ) { - gc = &(g->cells[i][j][k]); - if( max_atoms < gc->top ) - max_atoms = gc->top; - } - - my_max = (int)(MAX(max_atoms*SAFE_ZONE, MIN_GCELL_POPL)); - MPI_Allreduce( &my_max, &all_max, 1, MPI_INT, MPI_MAX, comm ); - - return all_max; -} - - -void Allocate_Grid( reax_system *system, MPI_Comm comm ) -{ - int i, j, k, l; - grid *g; - grid_cell *gc; - - g = &( system->my_grid ); - - /* allocate gcell reordering space */ - g->order = (ivec*) scalloc( g->total+1, sizeof(ivec), "g:order", comm ); - - /* allocate the gcells for the new grid */ - g->max_nbrs = (2*g->vlist_span[0]+1)*(2*g->vlist_span[1]+1)* - (2*g->vlist_span[2]+1)+3; - - g->cells = (grid_cell***) - scalloc( g->ncells[0], sizeof(grid_cell**), "gcells", comm ); - for( i = 0; i < g->ncells[0]; i++ ) { - g->cells[i] = (grid_cell**) - scalloc( g->ncells[1], sizeof(grid_cell*),"gcells[i]", comm ); - - for( j = 0; j < g->ncells[1]; ++j ) { - g->cells[i][j] = (grid_cell*) - scalloc( g->ncells[2], sizeof(grid_cell), "gcells[i][j]", comm ); - - for( k = 0; k < g->ncells[2]; k++ ) { - gc = &(g->cells[i][j][k]); - gc->top = gc->mark = gc->str = gc->end = 0; - gc->nbrs = (grid_cell**) - scalloc( g->max_nbrs, sizeof(grid_cell*), "g:nbrs", comm ); - gc->nbrs_x = (ivec*) - scalloc( g->max_nbrs, sizeof(ivec), "g:nbrs_x", comm ); - gc->nbrs_cp = (rvec*) - scalloc( g->max_nbrs, sizeof(rvec), "g:nbrs_cp", comm ); - for( l = 0; l < g->max_nbrs; ++l ) - gc->nbrs[l] = NULL; - } - } - } - - /* allocate atom id storage in gcells */ - g->max_atoms = Estimate_GCell_Population( system, comm ); - /* space for storing atom id's is required only for native cells */ - for( i = g->native_str[0]; i < g->native_end[0]; ++i ) - for( j = g->native_str[1]; j < g->native_end[1]; ++j ) - for( k = g->native_str[2]; k < g->native_end[2]; ++k ) - g->cells[i][j][k].atoms = (int*) scalloc( g->max_atoms, sizeof(int), - "g:atoms", comm ); -} - - -void Deallocate_Grid( grid *g ) -{ - int i, j, k; - grid_cell *gc; - - sfree( g->order, "g:order" ); - - /* deallocate the grid cells */ - for( i = 0; i < g->ncells[0]; i++ ) { - for( j = 0; j < g->ncells[1]; j++ ) { - for( k = 0; k < g->ncells[2]; k++ ) { - gc = &(g->cells[i][j][k]); - sfree( gc->nbrs, "g:nbrs" ); - sfree( gc->nbrs_x, "g:nbrs_x" ); - sfree( gc->nbrs_cp, "g:nbrs_cp" ); - if(gc->atoms != NULL ) - sfree( gc->atoms, "g:atoms" ); - } - sfree( g->cells[i][j], "g:cells[i][j]" ); - } - sfree( g->cells[i], "g:cells[i]" ); - } - sfree( g->cells, "g:cells" ); -} - - -int Allocate_MPI_Buffers( mpi_datatypes *mpi_data, int est_recv, - neighbor_proc *my_nbrs, char *msg ) -{ - int i; - mpi_out_data *mpi_buf; - MPI_Comm comm; - - comm = mpi_data->world; - - /* in buffers */ - mpi_data->in1_buffer = (void*) - scalloc( est_recv, sizeof(boundary_atom), "in1_buffer", comm ); - mpi_data->in2_buffer = (void*) - scalloc( est_recv, sizeof(boundary_atom), "in2_buffer", comm ); - - /* out buffers */ - for( i = 0; i < MAX_NBRS; ++i ) { - mpi_buf = &( mpi_data->out_buffers[i] ); - /* allocate storage for the neighbor processor i */ - mpi_buf->index = (int*) - scalloc( my_nbrs[i].est_send, sizeof(int), "mpibuf:index", comm ); - mpi_buf->out_atoms = (void*) - scalloc( my_nbrs[i].est_send, sizeof(boundary_atom), "mpibuf:out_atoms", - comm ); - } - - return SUCCESS; -} - - -void Deallocate_MPI_Buffers( mpi_datatypes *mpi_data ) -{ - int i; - mpi_out_data *mpi_buf; - - sfree( mpi_data->in1_buffer, "in1_buffer" ); - sfree( mpi_data->in2_buffer, "in2_buffer" ); - - for( i = 0; i < MAX_NBRS; ++i ) { - mpi_buf = &( mpi_data->out_buffers[i] ); - sfree( mpi_buf->index, "mpibuf:index" ); - sfree( mpi_buf->out_atoms, "mpibuf:out_atoms" ); - } -} - - void ReAllocate( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, mpi_datatypes *mpi_data ) { int num_bonds, est_3body, Hflag, ret; int renbr, newsize; reallocate_data *realloc; reax_list *far_nbrs; - grid *g; MPI_Comm comm; char msg[200]; int mincap = system->mincap; double safezone = system->safezone; double saferzone = system->saferzone; realloc = &(workspace->realloc); - g = &(system->my_grid); comm = mpi_data->world; - int nflag = 0; if( system->n >= DANGER_ZONE * system->local_cap || (0 && system->n <= LOOSE_ZONE * system->local_cap) ) { - nflag = 1; system->local_cap = MAX( (int)(system->n * safezone), mincap ); } int Nflag = 0; if( system->N >= DANGER_ZONE * system->total_cap || (0 && system->N <= LOOSE_ZONE * system->total_cap) ) { Nflag = 1; system->total_cap = MAX( (int)(system->N * safezone), mincap ); } if( Nflag ) { /* system */ ret = Allocate_System( system, system->local_cap, system->total_cap, msg ); if( ret != SUCCESS ) { fprintf( stderr, "not enough space for atom_list: total_cap=%d", system->total_cap ); fprintf( stderr, "terminating...\n" ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } /* workspace */ DeAllocate_Workspace( control, workspace ); ret = Allocate_Workspace( system, control, workspace, system->local_cap, system->total_cap, comm, msg ); if( ret != SUCCESS ) { fprintf( stderr, "no space for workspace: local_cap=%d total_cap=%d", system->local_cap, system->total_cap ); fprintf( stderr, "terminating...\n" ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } } renbr = (data->step - data->prev_steps) % control->reneighbor == 0; /* far neighbors */ if( renbr ) { far_nbrs = *lists + FAR_NBRS; if( Nflag || realloc->num_far >= far_nbrs->num_intrs * DANGER_ZONE ) { if( realloc->num_far > far_nbrs->num_intrs ) { fprintf( stderr, "step%d-ran out of space on far_nbrs: top=%d, max=%d", data->step, realloc->num_far, far_nbrs->num_intrs ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } newsize = static_cast<int> (MAX( realloc->num_far*safezone, mincap*MIN_NBRS )); Reallocate_Neighbor_List( far_nbrs, system->total_cap, newsize, comm ); realloc->num_far = 0; } } /* hydrogen bonds list */ if( control->hbond_cut > 0 ) { Hflag = 0; if( system->numH >= DANGER_ZONE * system->Hcap || (0 && system->numH <= LOOSE_ZONE * system->Hcap) ) { Hflag = 1; system->Hcap = int(MAX( system->numH * saferzone, mincap )); } if( Hflag || realloc->hbonds ) { ret = Reallocate_HBonds_List( system, (*lists)+HBONDS, comm ); realloc->hbonds = 0; } } /* bonds list */ num_bonds = est_3body = -1; if( Nflag || realloc->bonds ){ Reallocate_Bonds_List( system, (*lists)+BONDS, &num_bonds, &est_3body, comm ); realloc->bonds = 0; realloc->num_3body = MAX( realloc->num_3body, est_3body ); } /* 3-body list */ if( realloc->num_3body > 0 ) { Delete_List( (*lists)+THREE_BODIES, comm ); if( num_bonds == -1 ) num_bonds = ((*lists)+BONDS)->num_intrs; realloc->num_3body = (int)(MAX(realloc->num_3body*safezone, MIN_3BODIES)); if( !Make_List( num_bonds, realloc->num_3body, TYP_THREE_BODY, (*lists)+THREE_BODIES, comm ) ) { fprintf( stderr, "Problem in initializing angles list. Terminating!\n" ); MPI_Abort( comm, CANNOT_INITIALIZE ); } realloc->num_3body = -1; } } diff --git a/src/USER-REAXC/reaxc_allocate.h b/src/USER-REAXC/reaxc_allocate.h index 0ad5f1a71..f8814859a 100644 --- a/src/USER-REAXC/reaxc_allocate.h +++ b/src/USER-REAXC/reaxc_allocate.h @@ -1,54 +1,42 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #ifndef __ALLOCATE_H_ #define __ALLOCATE_H_ #include "reaxc_types.h" -int PreAllocate_Space( reax_system*, control_params*, storage*, MPI_Comm ); +int PreAllocate_Space( reax_system*, control_params*, storage*, MPI_Comm ); -void reax_atom_Copy( reax_atom*, reax_atom* ); int Allocate_System( reax_system*, int, int, char* ); void DeAllocate_System( reax_system* ); int Allocate_Workspace( reax_system*, control_params*, storage*, int, int, MPI_Comm, char* ); void DeAllocate_Workspace( control_params*, storage* ); -void Allocate_Grid( reax_system*, MPI_Comm ); -void Deallocate_Grid( grid* ); - -int Allocate_MPI_Buffers( mpi_datatypes*, int, neighbor_proc*, char* ); - -int Allocate_Matrix( sparse_matrix**, int, int, MPI_Comm ); - -int Allocate_HBond_List( int, int, int*, int*, reax_list* ); - -int Allocate_Bond_List( int, int*, reax_list* ); - void ReAllocate( reax_system*, control_params*, simulation_data*, storage*, reax_list**, mpi_datatypes* ); #endif diff --git a/src/USER-REAXC/reaxc_bond_orders.cpp b/src/USER-REAXC/reaxc_bond_orders.cpp index 11f862f64..7103f4829 100644 --- a/src/USER-REAXC/reaxc_bond_orders.cpp +++ b/src/USER-REAXC/reaxc_bond_orders.cpp @@ -1,600 +1,598 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_types.h" #include "reaxc_bond_orders.h" #include "reaxc_list.h" #include "reaxc_vector.h" void Add_dBond_to_Forces_NPT( int i, int pj, simulation_data *data, storage *workspace, reax_list **lists ) { reax_list *bonds = (*lists) + BONDS; bond_data *nbr_j, *nbr_k; bond_order_data *bo_ij, *bo_ji; dbond_coefficients coef; rvec temp, ext_press; ivec rel_box; int pk, k, j; /* Initializations */ nbr_j = &(bonds->select.bond_list[pj]); j = nbr_j->nbr; bo_ij = &(nbr_j->bo_data); bo_ji = &(bonds->select.bond_list[ nbr_j->sym_index ].bo_data); coef.C1dbo = bo_ij->C1dbo * (bo_ij->Cdbo + bo_ji->Cdbo); coef.C2dbo = bo_ij->C2dbo * (bo_ij->Cdbo + bo_ji->Cdbo); coef.C3dbo = bo_ij->C3dbo * (bo_ij->Cdbo + bo_ji->Cdbo); coef.C1dbopi = bo_ij->C1dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C2dbopi = bo_ij->C2dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C3dbopi = bo_ij->C3dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C4dbopi = bo_ij->C4dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C1dbopi2 = bo_ij->C1dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C2dbopi2 = bo_ij->C2dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C3dbopi2 = bo_ij->C3dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C4dbopi2 = bo_ij->C4dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C1dDelta = bo_ij->C1dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]); coef.C2dDelta = bo_ij->C2dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]); coef.C3dDelta = bo_ij->C3dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]); for( pk = Start_Index(i, bonds); pk < End_Index(i, bonds); ++pk ) { nbr_k = &(bonds->select.bond_list[pk]); k = nbr_k->nbr; rvec_Scale(temp, -coef.C2dbo, nbr_k->bo_data.dBOp); /*2nd, dBO*/ rvec_ScaledAdd(temp, -coef.C2dDelta, nbr_k->bo_data.dBOp);/*dDelta*/ rvec_ScaledAdd(temp, -coef.C3dbopi, nbr_k->bo_data.dBOp); /*3rd, dBOpi*/ rvec_ScaledAdd(temp, -coef.C3dbopi2, nbr_k->bo_data.dBOp);/*3rd, dBOpi2*/ /* force */ rvec_Add( workspace->f[k], temp ); /* pressure */ rvec_iMultiply( ext_press, nbr_k->rel_box, temp ); rvec_Add( data->my_ext_press, ext_press ); } /* then atom i itself */ rvec_Scale( temp, coef.C1dbo, bo_ij->dBOp ); /*1st,dBO*/ rvec_ScaledAdd( temp, coef.C2dbo, workspace->dDeltap_self[i] ); /*2nd,dBO*/ rvec_ScaledAdd( temp, coef.C1dDelta, bo_ij->dBOp ); /*1st,dBO*/ rvec_ScaledAdd( temp, coef.C2dDelta, workspace->dDeltap_self[i] );/*2nd,dBO*/ rvec_ScaledAdd( temp, coef.C1dbopi, bo_ij->dln_BOp_pi ); /*1st,dBOpi*/ rvec_ScaledAdd( temp, coef.C2dbopi, bo_ij->dBOp ); /*2nd,dBOpi*/ rvec_ScaledAdd( temp, coef.C3dbopi, workspace->dDeltap_self[i]);/*3rd,dBOpi*/ rvec_ScaledAdd( temp, coef.C1dbopi2, bo_ij->dln_BOp_pi2 ); /*1st,dBO_pi2*/ rvec_ScaledAdd( temp, coef.C2dbopi2, bo_ij->dBOp ); /*2nd,dBO_pi2*/ rvec_ScaledAdd( temp, coef.C3dbopi2, workspace->dDeltap_self[i] );/*3rd*/ /* force */ rvec_Add( workspace->f[i], temp ); for( pk = Start_Index(j, bonds); pk < End_Index(j, bonds); ++pk ) { nbr_k = &(bonds->select.bond_list[pk]); k = nbr_k->nbr; rvec_Scale( temp, -coef.C3dbo, nbr_k->bo_data.dBOp ); /*3rd,dBO*/ rvec_ScaledAdd( temp, -coef.C3dDelta, nbr_k->bo_data.dBOp);/*dDelta*/ rvec_ScaledAdd( temp, -coef.C4dbopi, nbr_k->bo_data.dBOp); /*4th,dBOpi*/ rvec_ScaledAdd( temp, -coef.C4dbopi2, nbr_k->bo_data.dBOp);/*4th,dBOpi2*/ /* force */ rvec_Add( workspace->f[k], temp ); /* pressure */ if( k != i ) { ivec_Sum( rel_box, nbr_k->rel_box, nbr_j->rel_box ); //rel_box(k, i) rvec_iMultiply( ext_press, rel_box, temp ); rvec_Add( data->my_ext_press, ext_press ); } } /* then atom j itself */ rvec_Scale( temp, -coef.C1dbo, bo_ij->dBOp ); /*1st, dBO*/ rvec_ScaledAdd( temp, coef.C3dbo, workspace->dDeltap_self[j] ); /*2nd, dBO*/ rvec_ScaledAdd( temp, -coef.C1dDelta, bo_ij->dBOp ); /*1st, dBO*/ rvec_ScaledAdd( temp, coef.C3dDelta, workspace->dDeltap_self[j]);/*2nd, dBO*/ rvec_ScaledAdd( temp, -coef.C1dbopi, bo_ij->dln_BOp_pi ); /*1st,dBOpi*/ rvec_ScaledAdd( temp, -coef.C2dbopi, bo_ij->dBOp ); /*2nd,dBOpi*/ rvec_ScaledAdd( temp, coef.C4dbopi, workspace->dDeltap_self[j]);/*3rd,dBOpi*/ rvec_ScaledAdd( temp, -coef.C1dbopi2, bo_ij->dln_BOp_pi2 ); /*1st,dBOpi2*/ rvec_ScaledAdd( temp, -coef.C2dbopi2, bo_ij->dBOp ); /*2nd,dBOpi2*/ rvec_ScaledAdd( temp,coef.C4dbopi2,workspace->dDeltap_self[j]);/*3rd,dBOpi2*/ /* force */ rvec_Add( workspace->f[j], temp ); /* pressure */ rvec_iMultiply( ext_press, nbr_j->rel_box, temp ); rvec_Add( data->my_ext_press, ext_press ); } void Add_dBond_to_Forces( reax_system *system, int i, int pj, storage *workspace, reax_list **lists ) { reax_list *bonds = (*lists) + BONDS; bond_data *nbr_j, *nbr_k; bond_order_data *bo_ij, *bo_ji; dbond_coefficients coef; int pk, k, j; /* Virial Tallying variables */ - real f_scaler; rvec fi_tmp, fj_tmp, fk_tmp, delij, delji, delki, delkj, temp; /* Initializations */ nbr_j = &(bonds->select.bond_list[pj]); j = nbr_j->nbr; bo_ij = &(nbr_j->bo_data); bo_ji = &(bonds->select.bond_list[ nbr_j->sym_index ].bo_data); coef.C1dbo = bo_ij->C1dbo * (bo_ij->Cdbo + bo_ji->Cdbo); coef.C2dbo = bo_ij->C2dbo * (bo_ij->Cdbo + bo_ji->Cdbo); coef.C3dbo = bo_ij->C3dbo * (bo_ij->Cdbo + bo_ji->Cdbo); coef.C1dbopi = bo_ij->C1dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C2dbopi = bo_ij->C2dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C3dbopi = bo_ij->C3dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C4dbopi = bo_ij->C4dbopi * (bo_ij->Cdbopi + bo_ji->Cdbopi); coef.C1dbopi2 = bo_ij->C1dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C2dbopi2 = bo_ij->C2dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C3dbopi2 = bo_ij->C3dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C4dbopi2 = bo_ij->C4dbopi2 * (bo_ij->Cdbopi2 + bo_ji->Cdbopi2); coef.C1dDelta = bo_ij->C1dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]); coef.C2dDelta = bo_ij->C2dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]); coef.C3dDelta = bo_ij->C3dbo * (workspace->CdDelta[i]+workspace->CdDelta[j]); // forces on i rvec_Scale( temp, coef.C1dbo, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C2dbo, workspace->dDeltap_self[i] ); rvec_ScaledAdd( temp, coef.C1dDelta, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C2dDelta, workspace->dDeltap_self[i] ); rvec_ScaledAdd( temp, coef.C1dbopi, bo_ij->dln_BOp_pi ); rvec_ScaledAdd( temp, coef.C2dbopi, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C3dbopi, workspace->dDeltap_self[i]); rvec_ScaledAdd( temp, coef.C1dbopi2, bo_ij->dln_BOp_pi2 ); rvec_ScaledAdd( temp, coef.C2dbopi2, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C3dbopi2, workspace->dDeltap_self[i] ); rvec_Add( workspace->f[i], temp ); if( system->pair_ptr->vflag_atom) { rvec_Scale(fi_tmp, -1.0, temp); rvec_ScaledSum( delij, 1., system->my_atoms[i].x,-1., system->my_atoms[j].x ); system->pair_ptr->v_tally(i,fi_tmp,delij); } // forces on j rvec_Scale( temp, -coef.C1dbo, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C3dbo, workspace->dDeltap_self[j] ); rvec_ScaledAdd( temp, -coef.C1dDelta, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C3dDelta, workspace->dDeltap_self[j]); rvec_ScaledAdd( temp, -coef.C1dbopi, bo_ij->dln_BOp_pi ); rvec_ScaledAdd( temp, -coef.C2dbopi, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C4dbopi, workspace->dDeltap_self[j]); rvec_ScaledAdd( temp, -coef.C1dbopi2, bo_ij->dln_BOp_pi2 ); rvec_ScaledAdd( temp, -coef.C2dbopi2, bo_ij->dBOp ); rvec_ScaledAdd( temp, coef.C4dbopi2, workspace->dDeltap_self[j]); rvec_Add( workspace->f[j], temp ); if( system->pair_ptr->vflag_atom) { rvec_Scale(fj_tmp, -1.0, temp); rvec_ScaledSum( delji, 1., system->my_atoms[j].x,-1., system->my_atoms[i].x ); system->pair_ptr->v_tally(j,fj_tmp,delji); } // forces on k: i neighbor for( pk = Start_Index(i, bonds); pk < End_Index(i, bonds); ++pk ) { nbr_k = &(bonds->select.bond_list[pk]); k = nbr_k->nbr; rvec_Scale( temp, -coef.C2dbo, nbr_k->bo_data.dBOp); rvec_ScaledAdd( temp, -coef.C2dDelta, nbr_k->bo_data.dBOp); rvec_ScaledAdd( temp, -coef.C3dbopi, nbr_k->bo_data.dBOp); rvec_ScaledAdd( temp, -coef.C3dbopi2, nbr_k->bo_data.dBOp); rvec_Add( workspace->f[k], temp ); if( system->pair_ptr->vflag_atom ) { rvec_Scale(fk_tmp, -1.0, temp); rvec_ScaledSum(delki,1.,system->my_atoms[k].x,-1.,system->my_atoms[i].x); system->pair_ptr->v_tally(k,fk_tmp,delki); rvec_ScaledSum(delkj,1.,system->my_atoms[k].x,-1.,system->my_atoms[j].x); system->pair_ptr->v_tally(k,fk_tmp,delkj); } } // forces on k: j neighbor for( pk = Start_Index(j, bonds); pk < End_Index(j, bonds); ++pk ) { nbr_k = &(bonds->select.bond_list[pk]); k = nbr_k->nbr; rvec_Scale( temp, -coef.C3dbo, nbr_k->bo_data.dBOp ); rvec_ScaledAdd( temp, -coef.C3dDelta, nbr_k->bo_data.dBOp); rvec_ScaledAdd( temp, -coef.C4dbopi, nbr_k->bo_data.dBOp); rvec_ScaledAdd( temp, -coef.C4dbopi2, nbr_k->bo_data.dBOp); rvec_Add( workspace->f[k], temp ); if( system->pair_ptr->vflag_atom ) { rvec_Scale(fk_tmp, -1.0, temp); rvec_ScaledSum(delki,1.,system->my_atoms[k].x,-1.,system->my_atoms[i].x); system->pair_ptr->v_tally(k,fk_tmp,delki); rvec_ScaledSum(delkj,1.,system->my_atoms[k].x,-1.,system->my_atoms[j].x); system->pair_ptr->v_tally(k,fk_tmp,delkj); } } } int BOp( storage *workspace, reax_list *bonds, real bo_cut, int i, int btop_i, far_neighbor_data *nbr_pj, single_body_parameters *sbp_i, single_body_parameters *sbp_j, two_body_parameters *twbp ) { int j, btop_j; real r2, C12, C34, C56; real Cln_BOp_s, Cln_BOp_pi, Cln_BOp_pi2; real BO, BO_s, BO_pi, BO_pi2; bond_data *ibond, *jbond; bond_order_data *bo_ij, *bo_ji; j = nbr_pj->nbr; r2 = SQR(nbr_pj->d); if( sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0 ) { C12 = twbp->p_bo1 * pow( nbr_pj->d / twbp->r_s, twbp->p_bo2 ); BO_s = (1.0 + bo_cut) * exp( C12 ); } else BO_s = C12 = 0.0; if( sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0 ) { C34 = twbp->p_bo3 * pow( nbr_pj->d / twbp->r_p, twbp->p_bo4 ); BO_pi = exp( C34 ); } else BO_pi = C34 = 0.0; if( sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0 ) { C56 = twbp->p_bo5 * pow( nbr_pj->d / twbp->r_pp, twbp->p_bo6 ); BO_pi2= exp( C56 ); } else BO_pi2 = C56 = 0.0; /* Initially BO values are the uncorrected ones, page 1 */ BO = BO_s + BO_pi + BO_pi2; if( BO >= bo_cut ) { /****** bonds i-j and j-i ******/ ibond = &( bonds->select.bond_list[btop_i] ); btop_j = End_Index( j, bonds ); jbond = &(bonds->select.bond_list[btop_j]); ibond->nbr = j; jbond->nbr = i; ibond->d = nbr_pj->d; jbond->d = nbr_pj->d; rvec_Copy( ibond->dvec, nbr_pj->dvec ); rvec_Scale( jbond->dvec, -1, nbr_pj->dvec ); ivec_Copy( ibond->rel_box, nbr_pj->rel_box ); ivec_Scale( jbond->rel_box, -1, nbr_pj->rel_box ); ibond->dbond_index = btop_i; jbond->dbond_index = btop_i; ibond->sym_index = btop_j; jbond->sym_index = btop_i; Set_End_Index( j, btop_j+1, bonds ); bo_ij = &( ibond->bo_data ); bo_ji = &( jbond->bo_data ); bo_ji->BO = bo_ij->BO = BO; bo_ji->BO_s = bo_ij->BO_s = BO_s; bo_ji->BO_pi = bo_ij->BO_pi = BO_pi; bo_ji->BO_pi2 = bo_ij->BO_pi2 = BO_pi2; /* Bond Order page2-3, derivative of total bond order prime */ Cln_BOp_s = twbp->p_bo2 * C12 / r2; Cln_BOp_pi = twbp->p_bo4 * C34 / r2; Cln_BOp_pi2 = twbp->p_bo6 * C56 / r2; /* Only dln_BOp_xx wrt. dr_i is stored here, note that dln_BOp_xx/dr_i = -dln_BOp_xx/dr_j and all others are 0 */ rvec_Scale(bo_ij->dln_BOp_s,-bo_ij->BO_s*Cln_BOp_s,ibond->dvec); rvec_Scale(bo_ij->dln_BOp_pi,-bo_ij->BO_pi*Cln_BOp_pi,ibond->dvec); rvec_Scale(bo_ij->dln_BOp_pi2, -bo_ij->BO_pi2*Cln_BOp_pi2,ibond->dvec); rvec_Scale(bo_ji->dln_BOp_s, -1., bo_ij->dln_BOp_s); rvec_Scale(bo_ji->dln_BOp_pi, -1., bo_ij->dln_BOp_pi ); rvec_Scale(bo_ji->dln_BOp_pi2, -1., bo_ij->dln_BOp_pi2 ); rvec_Scale( bo_ij->dBOp, -(bo_ij->BO_s * Cln_BOp_s + bo_ij->BO_pi * Cln_BOp_pi + bo_ij->BO_pi2 * Cln_BOp_pi2), ibond->dvec ); rvec_Scale( bo_ji->dBOp, -1., bo_ij->dBOp ); rvec_Add( workspace->dDeltap_self[i], bo_ij->dBOp ); rvec_Add( workspace->dDeltap_self[j], bo_ji->dBOp ); bo_ij->BO_s -= bo_cut; bo_ij->BO -= bo_cut; bo_ji->BO_s -= bo_cut; bo_ji->BO -= bo_cut; workspace->total_bond_order[i] += bo_ij->BO; //currently total_BOp workspace->total_bond_order[j] += bo_ji->BO; //currently total_BOp bo_ij->Cdbo = bo_ij->Cdbopi = bo_ij->Cdbopi2 = 0.0; bo_ji->Cdbo = bo_ji->Cdbopi = bo_ji->Cdbopi2 = 0.0; return 1; } return 0; } int compare_bonds( const void *p1, const void *p2 ) { return ((bond_data *)p1)->nbr - ((bond_data *)p2)->nbr; } void BO( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control ) { int i, j, pj, type_i, type_j; - int start_i, end_i, sym_index, num_bonds; + int start_i, end_i, sym_index; real val_i, Deltap_i, Deltap_boc_i; real val_j, Deltap_j, Deltap_boc_j; real f1, f2, f3, f4, f5, f4f5, exp_f4, exp_f5; real exp_p1i, exp_p2i, exp_p1j, exp_p2j; real temp, u1_ij, u1_ji, Cf1A_ij, Cf1B_ij, Cf1_ij, Cf1_ji; real Cf45_ij, Cf45_ji, p_lp1; //u_ij, u_ji real A0_ij, A1_ij, A2_ij, A2_ji, A3_ij, A3_ji; real explp1, p_boc1, p_boc2; single_body_parameters *sbp_i, *sbp_j; two_body_parameters *twbp; bond_order_data *bo_ij, *bo_ji; reax_list *bonds = (*lists) + BONDS; - num_bonds = 0; p_boc1 = system->reax_param.gp.l[0]; p_boc2 = system->reax_param.gp.l[1]; /* Calculate Deltaprime, Deltaprime_boc values */ for( i = 0; i < system->N; ++i ) { type_i = system->my_atoms[i].type; if (type_i < 0) continue; sbp_i = &(system->reax_param.sbp[type_i]); workspace->Deltap[i] = workspace->total_bond_order[i] - sbp_i->valency; workspace->Deltap_boc[i] = workspace->total_bond_order[i] - sbp_i->valency_val; workspace->total_bond_order[i] = 0; } /* Corrected Bond Order calculations */ for( i = 0; i < system->N; ++i ) { type_i = system->my_atoms[i].type; if (type_i < 0) continue; sbp_i = &(system->reax_param.sbp[type_i]); val_i = sbp_i->valency; Deltap_i = workspace->Deltap[i]; Deltap_boc_i = workspace->Deltap_boc[i]; start_i = Start_Index(i, bonds); end_i = End_Index(i, bonds); for( pj = start_i; pj < end_i; ++pj ) { j = bonds->select.bond_list[pj].nbr; type_j = system->my_atoms[j].type; if (type_j < 0) continue; bo_ij = &( bonds->select.bond_list[pj].bo_data ); // fprintf( stderr, "\tj:%d - ubo: %8.3f\n", j+1, bo_ij->BO ); if( i < j || workspace->bond_mark[j] > 3 ) { twbp = &( system->reax_param.tbp[type_i][type_j] ); if( twbp->ovc < 0.001 && twbp->v13cor < 0.001 ) { bo_ij->C1dbo = 1.000000; bo_ij->C2dbo = 0.000000; bo_ij->C3dbo = 0.000000; bo_ij->C1dbopi = bo_ij->BO_pi; bo_ij->C2dbopi = 0.000000; bo_ij->C3dbopi = 0.000000; bo_ij->C4dbopi = 0.000000; bo_ij->C1dbopi2 = bo_ij->BO_pi2; bo_ij->C2dbopi2 = 0.000000; bo_ij->C3dbopi2 = 0.000000; bo_ij->C4dbopi2 = 0.000000; } else { val_j = system->reax_param.sbp[type_j].valency; Deltap_j = workspace->Deltap[j]; Deltap_boc_j = workspace->Deltap_boc[j]; /* on page 1 */ if( twbp->ovc >= 0.001 ) { /* Correction for overcoordination */ exp_p1i = exp( -p_boc1 * Deltap_i ); exp_p2i = exp( -p_boc2 * Deltap_i ); exp_p1j = exp( -p_boc1 * Deltap_j ); exp_p2j = exp( -p_boc2 * Deltap_j ); f2 = exp_p1i + exp_p1j; f3 = -1.0 / p_boc2 * log( 0.5 * ( exp_p2i + exp_p2j ) ); f1 = 0.5 * ( ( val_i + f2 )/( val_i + f2 + f3 ) + ( val_j + f2 )/( val_j + f2 + f3 ) ); temp = f2 + f3; u1_ij = val_i + temp; u1_ji = val_j + temp; Cf1A_ij = 0.5 * f3 * (1.0 / SQR( u1_ij ) + 1.0 / SQR( u1_ji )); Cf1B_ij = -0.5 * (( u1_ij - f3 ) / SQR( u1_ij ) + ( u1_ji - f3 ) / SQR( u1_ji )); Cf1_ij = 0.50 * ( -p_boc1 * exp_p1i / u1_ij - ((val_i+f2) / SQR(u1_ij)) * ( -p_boc1 * exp_p1i + exp_p2i / ( exp_p2i + exp_p2j ) ) + -p_boc1 * exp_p1i / u1_ji - ((val_j+f2) / SQR(u1_ji)) * ( -p_boc1 * exp_p1i + exp_p2i / ( exp_p2i + exp_p2j ) )); Cf1_ji = -Cf1A_ij * p_boc1 * exp_p1j + Cf1B_ij * exp_p2j / ( exp_p2i + exp_p2j ); } else { /* No overcoordination correction! */ f1 = 1.0; Cf1_ij = Cf1_ji = 0.0; } if( twbp->v13cor >= 0.001 ) { /* Correction for 1-3 bond orders */ exp_f4 =exp(-(twbp->p_boc4 * SQR( bo_ij->BO ) - Deltap_boc_i) * twbp->p_boc3 + twbp->p_boc5); exp_f5 =exp(-(twbp->p_boc4 * SQR( bo_ij->BO ) - Deltap_boc_j) * twbp->p_boc3 + twbp->p_boc5); f4 = 1. / (1. + exp_f4); f5 = 1. / (1. + exp_f5); f4f5 = f4 * f5; /* Bond Order pages 8-9, derivative of f4 and f5 */ Cf45_ij = -f4 * exp_f4; Cf45_ji = -f5 * exp_f5; } else { f4 = f5 = f4f5 = 1.0; Cf45_ij = Cf45_ji = 0.0; } /* Bond Order page 10, derivative of total bond order */ A0_ij = f1 * f4f5; A1_ij = -2 * twbp->p_boc3 * twbp->p_boc4 * bo_ij->BO * (Cf45_ij + Cf45_ji); A2_ij = Cf1_ij / f1 + twbp->p_boc3 * Cf45_ij; A2_ji = Cf1_ji / f1 + twbp->p_boc3 * Cf45_ji; A3_ij = A2_ij + Cf1_ij / f1; A3_ji = A2_ji + Cf1_ji / f1; /* find corrected bond orders and their derivative coef */ bo_ij->BO = bo_ij->BO * A0_ij; bo_ij->BO_pi = bo_ij->BO_pi * A0_ij *f1; bo_ij->BO_pi2= bo_ij->BO_pi2* A0_ij *f1; bo_ij->BO_s = bo_ij->BO - ( bo_ij->BO_pi + bo_ij->BO_pi2 ); bo_ij->C1dbo = A0_ij + bo_ij->BO * A1_ij; bo_ij->C2dbo = bo_ij->BO * A2_ij; bo_ij->C3dbo = bo_ij->BO * A2_ji; bo_ij->C1dbopi = f1*f1*f4*f5; bo_ij->C2dbopi = bo_ij->BO_pi * A1_ij; bo_ij->C3dbopi = bo_ij->BO_pi * A3_ij; bo_ij->C4dbopi = bo_ij->BO_pi * A3_ji; bo_ij->C1dbopi2 = f1*f1*f4*f5; bo_ij->C2dbopi2 = bo_ij->BO_pi2 * A1_ij; bo_ij->C3dbopi2 = bo_ij->BO_pi2 * A3_ij; bo_ij->C4dbopi2 = bo_ij->BO_pi2 * A3_ji; } /* neglect bonds that are < 1e-10 */ if( bo_ij->BO < 1e-10 ) bo_ij->BO = 0.0; if( bo_ij->BO_s < 1e-10 ) bo_ij->BO_s = 0.0; if( bo_ij->BO_pi < 1e-10 ) bo_ij->BO_pi = 0.0; if( bo_ij->BO_pi2 < 1e-10 ) bo_ij->BO_pi2 = 0.0; workspace->total_bond_order[i] += bo_ij->BO; //now keeps total_BO } else { /* We only need to update bond orders from bo_ji everything else is set in uncorrected_bo calculations */ sym_index = bonds->select.bond_list[pj].sym_index; bo_ji = &(bonds->select.bond_list[ sym_index ].bo_data); bo_ij->BO = bo_ji->BO; bo_ij->BO_s = bo_ji->BO_s; bo_ij->BO_pi = bo_ji->BO_pi; bo_ij->BO_pi2 = bo_ji->BO_pi2; workspace->total_bond_order[i] += bo_ij->BO;// now keeps total_BO } } } p_lp1 = system->reax_param.gp.l[15]; for( j = 0; j < system->N; ++j ){ type_j = system->my_atoms[j].type; if (type_j < 0) continue; sbp_j = &(system->reax_param.sbp[ type_j ]); workspace->Delta[j] = workspace->total_bond_order[j] - sbp_j->valency; workspace->Delta_e[j] = workspace->total_bond_order[j] - sbp_j->valency_e; workspace->Delta_boc[j] = workspace->total_bond_order[j] - sbp_j->valency_boc; workspace->Delta_val[j] = workspace->total_bond_order[j] - sbp_j->valency_val; workspace->vlpex[j] = workspace->Delta_e[j] - 2.0 * (int)(workspace->Delta_e[j]/2.0); explp1 = exp(-p_lp1 * SQR(2.0 + workspace->vlpex[j])); workspace->nlp[j] = explp1 - (int)(workspace->Delta_e[j] / 2.0); workspace->Delta_lp[j] = sbp_j->nlp_opt - workspace->nlp[j]; workspace->Clp[j] = 2.0 * p_lp1 * explp1 * (2.0 + workspace->vlpex[j]); workspace->dDelta_lp[j] = workspace->Clp[j]; if( sbp_j->mass > 21.0 ) { workspace->nlp_temp[j] = 0.5 * (sbp_j->valency_e - sbp_j->valency); workspace->Delta_lp_temp[j] = sbp_j->nlp_opt - workspace->nlp_temp[j]; workspace->dDelta_lp_temp[j] = 0.; } else { workspace->nlp_temp[j] = workspace->nlp[j]; workspace->Delta_lp_temp[j] = sbp_j->nlp_opt - workspace->nlp_temp[j]; workspace->dDelta_lp_temp[j] = workspace->Clp[j]; } } } diff --git a/src/USER-REAXC/reaxc_control.cpp b/src/USER-REAXC/reaxc_control.cpp index eadce53a0..9d067c16a 100644 --- a/src/USER-REAXC/reaxc_control.cpp +++ b/src/USER-REAXC/reaxc_control.cpp @@ -1,385 +1,385 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_control.h" #include "reaxc_tool_box.h" char Read_Control_File( char *control_file, control_params* control, output_controls *out_control ) { FILE *fp; char *s, **tmp; - int c,i,ival; + int i,ival; real val; /* open control file */ if ( (fp = fopen( control_file, "r" ) ) == NULL ) { fprintf( stderr, "error opening the control file! terminating...\n" ); MPI_Abort( MPI_COMM_WORLD, FILE_NOT_FOUND ); } /* assign default values */ strcpy( control->sim_name, "simulate" ); control->ensemble = NVE; control->nsteps = 0; control->dt = 0.25; control->nprocs = 1; control->procs_by_dim[0] = 1; control->procs_by_dim[1] = 1; control->procs_by_dim[2] = 1; control->geo_format = 1; control->restart = 0; out_control->restart_format = WRITE_BINARY; out_control->restart_freq = 0; control->reposition_atoms = 0; control->restrict_bonds = 0; control->remove_CoM_vel = 25; out_control->debug_level = 0; out_control->energy_update_freq = 0; control->reneighbor = 1; control->vlist_cut = control->nonb_cut; control->bond_cut = 5.0; control->bg_cut = 0.3; control->thb_cut = 0.001; control->thb_cutsq = 0.00001; control->hbond_cut = 7.5; control->tabulate = 0; control->qeq_freq = 1; control->q_err = 1e-6; control->refactor = 100; control->droptol = 1e-2;; control->T_init = 0.; control->T_final = 300.; control->Tau_T = 500.0; control->T_mode = 0; control->T_rate = 1.; control->T_freq = 1.; control->P[0] = control->P[1] = control->P[2] = 0.000101325; control->Tau_P[0] = control->Tau_P[1] = control->Tau_P[2] = 500.0; control->Tau_PT[0] = control->Tau_PT[1] = control->Tau_PT[2] = 500.0; control->compressibility = 1.0; control->press_mode = 0; control->virial = 0; out_control->write_steps = 0; out_control->traj_compress = 0; out_control->traj_method = REG_TRAJ; strcpy( out_control->traj_title, "default_title" ); out_control->atom_info = 0; out_control->bond_info = 0; out_control->angle_info = 0; control->molecular_analysis = 0; control->dipole_anal = 0; control->freq_dipole_anal = 0; control->diffusion_coef = 0; control->freq_diffusion_coef = 0; control->restrict_type = 0; /* memory allocations */ s = (char*) malloc(sizeof(char)*MAX_LINE); tmp = (char**) malloc(sizeof(char*)*MAX_TOKENS); for (i=0; i < MAX_TOKENS; i++) tmp[i] = (char*) malloc(sizeof(char)*MAX_LINE); /* read control parameters file */ while (!feof(fp)) { fgets( s, MAX_LINE, fp ); - c = Tokenize( s, &tmp ); + Tokenize( s, &tmp ); if( strcmp(tmp[0], "simulation_name") == 0 ) { strcpy( control->sim_name, tmp[1] ); } else if( strcmp(tmp[0], "ensemble_type") == 0 ) { ival = atoi(tmp[1]); control->ensemble = ival; if( ival == iNPT || ival ==sNPT || ival == NPT ) control->virial = 1; } else if( strcmp(tmp[0], "nsteps") == 0 ) { ival = atoi(tmp[1]); control->nsteps = ival; } else if( strcmp(tmp[0], "dt") == 0) { val = atof(tmp[1]); control->dt = val * 1.e-3; // convert dt from fs to ps! } else if( strcmp(tmp[0], "proc_by_dim") == 0 ) { ival = atoi(tmp[1]); control->procs_by_dim[0] = ival; ival = atoi(tmp[2]); control->procs_by_dim[1] = ival; ival = atoi(tmp[3]); control->procs_by_dim[2] = ival; control->nprocs = control->procs_by_dim[0]*control->procs_by_dim[1]* control->procs_by_dim[2]; } else if( strcmp(tmp[0], "random_vel") == 0 ) { ival = atoi(tmp[1]); control->random_vel = ival; } else if( strcmp(tmp[0], "restart_format") == 0 ) { ival = atoi(tmp[1]); out_control->restart_format = ival; } else if( strcmp(tmp[0], "restart_freq") == 0 ) { ival = atoi(tmp[1]); out_control->restart_freq = ival; } else if( strcmp(tmp[0], "reposition_atoms") == 0 ) { ival = atoi(tmp[1]); control->reposition_atoms = ival; } else if( strcmp(tmp[0], "restrict_bonds") == 0 ) { ival = atoi( tmp[1] ); control->restrict_bonds = ival; } else if( strcmp(tmp[0], "remove_CoM_vel") == 0 ) { ival = atoi(tmp[1]); control->remove_CoM_vel = ival; } else if( strcmp(tmp[0], "debug_level") == 0 ) { ival = atoi(tmp[1]); out_control->debug_level = ival; } else if( strcmp(tmp[0], "energy_update_freq") == 0 ) { ival = atoi(tmp[1]); out_control->energy_update_freq = ival; } else if( strcmp(tmp[0], "reneighbor") == 0 ) { ival = atoi( tmp[1] ); control->reneighbor = ival; } else if( strcmp(tmp[0], "vlist_buffer") == 0 ) { val = atof(tmp[1]); control->vlist_cut= val + control->nonb_cut; } else if( strcmp(tmp[0], "nbrhood_cutoff") == 0 ) { val = atof(tmp[1]); control->bond_cut = val; } else if( strcmp(tmp[0], "bond_graph_cutoff") == 0 ) { val = atof(tmp[1]); control->bg_cut = val; } else if( strcmp(tmp[0], "thb_cutoff") == 0 ) { val = atof(tmp[1]); control->thb_cut = val; } else if( strcmp(tmp[0], "thb_cutoff_sq") == 0 ) { val = atof(tmp[1]); control->thb_cutsq = val; } else if( strcmp(tmp[0], "hbond_cutoff") == 0 ) { val = atof( tmp[1] ); control->hbond_cut = val; } else if( strcmp(tmp[0], "ghost_cutoff") == 0 ) { val = atof(tmp[1]); control->user_ghost_cut = val; } else if( strcmp(tmp[0], "tabulate_long_range") == 0 ) { ival = atoi( tmp[1] ); control->tabulate = ival; } else if( strcmp(tmp[0], "qeq_freq") == 0 ) { ival = atoi( tmp[1] ); control->qeq_freq = ival; } else if( strcmp(tmp[0], "q_err") == 0 ) { val = atof( tmp[1] ); control->q_err = val; } else if( strcmp(tmp[0], "ilu_refactor") == 0 ) { ival = atoi( tmp[1] ); control->refactor = ival; } else if( strcmp(tmp[0], "ilu_droptol") == 0 ) { val = atof( tmp[1] ); control->droptol = val; } else if( strcmp(tmp[0], "temp_init") == 0 ) { val = atof(tmp[1]); control->T_init = val; if( control->T_init < 0.1 ) control->T_init = 0.1; } else if( strcmp(tmp[0], "temp_final") == 0 ) { val = atof(tmp[1]); control->T_final = val; if( control->T_final < 0.1 ) control->T_final = 0.1; } else if( strcmp(tmp[0], "t_mass") == 0 ) { val = atof(tmp[1]); control->Tau_T = val * 1.e-3; // convert t_mass from fs to ps } else if( strcmp(tmp[0], "t_mode") == 0 ) { ival = atoi(tmp[1]); control->T_mode = ival; } else if( strcmp(tmp[0], "t_rate") == 0 ) { val = atof(tmp[1]); control->T_rate = val; } else if( strcmp(tmp[0], "t_freq") == 0 ) { val = atof(tmp[1]); control->T_freq = val; } else if( strcmp(tmp[0], "pressure") == 0 ) { if( control->ensemble == iNPT ) { control->P[0] = control->P[1] = control->P[2] = atof(tmp[1]); } else if( control->ensemble == sNPT ) { control->P[0] = atof(tmp[1]); control->P[1] = atof(tmp[2]); control->P[2] = atof(tmp[3]); } } else if( strcmp(tmp[0], "p_mass") == 0 ) { // convert p_mass from fs to ps if( control->ensemble == iNPT ) { control->Tau_P[0] = control->Tau_P[1] = control->Tau_P[2] = atof(tmp[1]) * 1.e-3; } else if( control->ensemble == sNPT ) { control->Tau_P[0] = atof(tmp[1]) * 1.e-3; control->Tau_P[1] = atof(tmp[2]) * 1.e-3; control->Tau_P[2] = atof(tmp[3]) * 1.e-3; } } else if( strcmp(tmp[0], "pt_mass") == 0 ) { val = atof(tmp[1]); control->Tau_PT[0] = control->Tau_PT[1] = control->Tau_PT[2] = val * 1.e-3; // convert pt_mass from fs to ps } else if( strcmp(tmp[0], "compress") == 0 ) { val = atof(tmp[1]); control->compressibility = val; } else if( strcmp(tmp[0], "press_mode") == 0 ) { ival = atoi(tmp[1]); control->press_mode = ival; } else if( strcmp(tmp[0], "geo_format") == 0 ) { ival = atoi( tmp[1] ); control->geo_format = ival; } else if( strcmp(tmp[0], "write_freq") == 0 ) { ival = atoi(tmp[1]); out_control->write_steps = ival; } else if( strcmp(tmp[0], "traj_compress") == 0 ) { ival = atoi(tmp[1]); out_control->traj_compress = ival; } else if( strcmp(tmp[0], "traj_method") == 0 ) { ival = atoi(tmp[1]); out_control->traj_method = ival; } else if( strcmp(tmp[0], "traj_title") == 0 ) { strcpy( out_control->traj_title, tmp[1] ); } else if( strcmp(tmp[0], "atom_info") == 0 ) { ival = atoi(tmp[1]); out_control->atom_info += ival * 4; } else if( strcmp(tmp[0], "atom_velocities") == 0 ) { ival = atoi(tmp[1]); out_control->atom_info += ival * 2; } else if( strcmp(tmp[0], "atom_forces") == 0 ) { ival = atoi(tmp[1]); out_control->atom_info += ival * 1; } else if( strcmp(tmp[0], "bond_info") == 0 ) { ival = atoi(tmp[1]); out_control->bond_info = ival; } else if( strcmp(tmp[0], "angle_info") == 0 ) { ival = atoi(tmp[1]); out_control->angle_info = ival; } else if( strcmp(tmp[0], "molecular_analysis") == 0 ) { ival = atoi(tmp[1]); control->molecular_analysis = ival; } else if( strcmp(tmp[0], "ignore") == 0 ) { control->num_ignored = atoi(tmp[1]); for( i = 0; i < control->num_ignored; ++i ) control->ignore[atoi(tmp[i+2])] = 1; } else if( strcmp(tmp[0], "dipole_anal") == 0 ) { ival = atoi(tmp[1]); control->dipole_anal = ival; } else if( strcmp(tmp[0], "freq_dipole_anal") == 0 ) { ival = atoi(tmp[1]); control->freq_dipole_anal = ival; } else if( strcmp(tmp[0], "diffusion_coef") == 0 ) { ival = atoi(tmp[1]); control->diffusion_coef = ival; } else if( strcmp(tmp[0], "freq_diffusion_coef") == 0 ) { ival = atoi(tmp[1]); control->freq_diffusion_coef = ival; } else if( strcmp(tmp[0], "restrict_type") == 0 ) { ival = atoi(tmp[1]); control->restrict_type = ival; } else { fprintf( stderr, "WARNING: unknown parameter %s\n", tmp[0] ); MPI_Abort( MPI_COMM_WORLD, 15 ); } } /* determine target T */ if( control->T_mode == 0 ) control->T = control->T_final; else control->T = control->T_init; /* free memory allocations at the top */ for( i = 0; i < MAX_TOKENS; i++ ) free( tmp[i] ); free( tmp ); free( s ); fclose(fp); return SUCCESS; } diff --git a/src/USER-REAXC/reaxc_forces.cpp b/src/USER-REAXC/reaxc_forces.cpp index d581cbebb..b9fd78dd7 100644 --- a/src/USER-REAXC/reaxc_forces.cpp +++ b/src/USER-REAXC/reaxc_forces.cpp @@ -1,680 +1,674 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_forces.h" #include "reaxc_bond_orders.h" #include "reaxc_bonds.h" -#include "reaxc_basic_comm.h" #include "reaxc_hydrogen_bonds.h" #include "reaxc_io_tools.h" #include "reaxc_list.h" #include "reaxc_lookup.h" #include "reaxc_multi_body.h" #include "reaxc_nonbonded.h" #include "reaxc_tool_box.h" #include "reaxc_torsion_angles.h" #include "reaxc_valence_angles.h" #include "reaxc_vector.h" interaction_function Interaction_Functions[NUM_INTRS]; void Dummy_Interaction( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control ) { } void Init_Force_Functions( control_params *control ) { Interaction_Functions[0] = BO; Interaction_Functions[1] = Bonds; //Dummy_Interaction; Interaction_Functions[2] = Atom_Energy; //Dummy_Interaction; Interaction_Functions[3] = Valence_Angles; //Dummy_Interaction; Interaction_Functions[4] = Torsion_Angles; //Dummy_Interaction; if( control->hbond_cut > 0 ) Interaction_Functions[5] = Hydrogen_Bonds; else Interaction_Functions[5] = Dummy_Interaction; Interaction_Functions[6] = Dummy_Interaction; //empty Interaction_Functions[7] = Dummy_Interaction; //empty Interaction_Functions[8] = Dummy_Interaction; //empty Interaction_Functions[9] = Dummy_Interaction; //empty } void Compute_Bonded_Forces( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control, MPI_Comm comm ) { int i; /* Implement all force calls as function pointers */ for( i = 0; i < NUM_INTRS; i++ ) { (Interaction_Functions[i])( system, control, data, workspace, lists, out_control ); } } void Compute_NonBonded_Forces( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control, MPI_Comm comm ) { /* van der Waals and Coulomb interactions */ if( control->tabulate == 0 ) vdW_Coulomb_Energy( system, control, data, workspace, lists, out_control ); else Tabulated_vdW_Coulomb_Energy( system, control, data, workspace, lists, out_control ); } void Compute_Total_Force( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, mpi_datatypes *mpi_data ) { int i, pj; reax_list *bonds = (*lists) + BONDS; for( i = 0; i < system->N; ++i ) for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) if( i < bonds->select.bond_list[pj].nbr ) { if( control->virial == 0 ) Add_dBond_to_Forces( system, i, pj, workspace, lists ); else Add_dBond_to_Forces_NPT( i, pj, data, workspace, lists ); } } void Validate_Lists( reax_system *system, storage *workspace, reax_list **lists, int step, int n, int N, int numH, MPI_Comm comm ) { int i, comp, Hindex; reax_list *bonds, *hbonds; - reallocate_data *realloc; - realloc = &(workspace->realloc); double saferzone = system->saferzone; /* bond list */ if( N > 0 ) { bonds = *lists + BONDS; for( i = 0; i < N; ++i ) { system->my_atoms[i].num_bonds = MAX(Num_Entries(i,bonds)*2, MIN_BONDS); if( i < N-1 ) comp = Start_Index(i+1, bonds); else comp = bonds->num_intrs; if( End_Index(i, bonds) > comp ) { fprintf( stderr, "step%d-bondchk failed: i=%d end(i)=%d str(i+1)=%d\n", step, i, End_Index(i,bonds), comp ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } } } /* hbonds list */ if( numH > 0 ) { hbonds = *lists + HBONDS; for( i = 0; i < N; ++i ) { Hindex = system->my_atoms[i].Hindex; if( Hindex > -1 ) { system->my_atoms[i].num_hbonds = (int)(MAX( Num_Entries(Hindex, hbonds)*saferzone, MIN_HBONDS )); //if( Num_Entries(i, hbonds) >= //(Start_Index(i+1,hbonds)-Start_Index(i,hbonds))*0.90/*DANGER_ZONE*/){ // workspace->realloc.hbonds = 1; if( Hindex < numH-1 ) comp = Start_Index(Hindex+1, hbonds); else comp = hbonds->num_intrs; if( End_Index(Hindex, hbonds) > comp ) { fprintf(stderr,"step%d-hbondchk failed: H=%d end(H)=%d str(H+1)=%d\n", step, Hindex, End_Index(Hindex,hbonds), comp ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } } } } } real Compute_H( real r, real gamma, real *ctap ) { real taper, dr3gamij_1, dr3gamij_3; taper = ctap[7] * r + ctap[6]; taper = taper * r + ctap[5]; taper = taper * r + ctap[4]; taper = taper * r + ctap[3]; taper = taper * r + ctap[2]; taper = taper * r + ctap[1]; taper = taper * r + ctap[0]; dr3gamij_1 = ( r*r*r + gamma ); dr3gamij_3 = pow( dr3gamij_1 , 0.33333333333333 ); return taper * EV_to_KCALpMOL / dr3gamij_3; } real Compute_tabH( real r_ij, int ti, int tj ) { int r, tmin, tmax; real val, dif, base; LR_lookup_table *t; tmin = MIN( ti, tj ); tmax = MAX( ti, tj ); t = &( LR[tmin][tmax] ); /* cubic spline interpolation */ r = (int)(r_ij * t->inv_dx); if( r == 0 ) ++r; base = (real)(r+1) * t->dx; dif = r_ij - base; val = ((t->ele[r].d*dif + t->ele[r].c)*dif + t->ele[r].b)*dif + t->ele[r].a; val *= EV_to_KCALpMOL / C_ele; return val; } void Init_Forces( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control, MPI_Comm comm ) { int i, j, pj; int start_i, end_i; int type_i, type_j; int Htop, btop_i, btop_j, num_bonds, num_hbonds; int ihb, jhb, ihb_top, jhb_top; int local, flag, renbr; real r_ij, cutoff; sparse_matrix *H; reax_list *far_nbrs, *bonds, *hbonds; single_body_parameters *sbp_i, *sbp_j; two_body_parameters *twbp; far_neighbor_data *nbr_pj; reax_atom *atom_i, *atom_j; far_nbrs = *lists + FAR_NBRS; bonds = *lists + BONDS; hbonds = *lists + HBONDS; for( i = 0; i < system->n; ++i ) workspace->bond_mark[i] = 0; for( i = system->n; i < system->N; ++i ) { workspace->bond_mark[i] = 1000; // put ghost atoms to an infinite distance } H = workspace->H; H->n = system->n; Htop = 0; num_bonds = 0; num_hbonds = 0; btop_i = btop_j = 0; renbr = (data->step-data->prev_steps) % control->reneighbor == 0; for( i = 0; i < system->N; ++i ) { atom_i = &(system->my_atoms[i]); type_i = atom_i->type; if (type_i < 0) continue; start_i = Start_Index(i, far_nbrs); end_i = End_Index(i, far_nbrs); btop_i = End_Index( i, bonds ); sbp_i = &(system->reax_param.sbp[type_i]); if( i < system->n ) { local = 1; cutoff = control->nonb_cut; } else { local = 0; cutoff = control->bond_cut; } ihb = -1; ihb_top = -1; if( local ) { H->start[i] = Htop; H->entries[Htop].j = i; H->entries[Htop].val = sbp_i->eta; ++Htop; if( control->hbond_cut > 0 ) { ihb = sbp_i->p_hbond; if( ihb == 1 ) ihb_top = End_Index( atom_i->Hindex, hbonds ); else ihb_top = -1; } } /* update i-j distance - check if j is within cutoff */ for( pj = start_i; pj < end_i; ++pj ) { nbr_pj = &( far_nbrs->select.far_nbr_list[pj] ); j = nbr_pj->nbr; atom_j = &(system->my_atoms[j]); if( renbr ) { if(nbr_pj->d <= cutoff) flag = 1; else flag = 0; } else{ nbr_pj->dvec[0] = atom_j->x[0] - atom_i->x[0]; nbr_pj->dvec[1] = atom_j->x[1] - atom_i->x[1]; nbr_pj->dvec[2] = atom_j->x[2] - atom_i->x[2]; nbr_pj->d = rvec_Norm_Sqr( nbr_pj->dvec ); if( nbr_pj->d <= SQR(cutoff) ) { nbr_pj->d = sqrt(nbr_pj->d); flag = 1; } else { flag = 0; } } if( flag ){ type_j = atom_j->type; if (type_j < 0) continue; r_ij = nbr_pj->d; sbp_j = &(system->reax_param.sbp[type_j]); twbp = &(system->reax_param.tbp[type_i][type_j]); if( local ) { /* H matrix entry */ if( j < system->n || atom_i->orig_id < atom_j->orig_id ) {//tryQEq||1 H->entries[Htop].j = j; if( control->tabulate == 0 ) H->entries[Htop].val = Compute_H(r_ij,twbp->gamma,workspace->Tap); else H->entries[Htop].val = Compute_tabH(r_ij, type_i, type_j); ++Htop; } /* hydrogen bond lists */ if( control->hbond_cut > 0 && (ihb==1 || ihb==2) && nbr_pj->d <= control->hbond_cut ) { jhb = sbp_j->p_hbond; if( ihb == 1 && jhb == 2 ) { hbonds->select.hbond_list[ihb_top].nbr = j; hbonds->select.hbond_list[ihb_top].scl = 1; hbonds->select.hbond_list[ihb_top].ptr = nbr_pj; ++ihb_top; ++num_hbonds; } else if( j < system->n && ihb == 2 && jhb == 1 ) { jhb_top = End_Index( atom_j->Hindex, hbonds ); hbonds->select.hbond_list[jhb_top].nbr = i; hbonds->select.hbond_list[jhb_top].scl = -1; hbonds->select.hbond_list[jhb_top].ptr = nbr_pj; Set_End_Index( atom_j->Hindex, jhb_top+1, hbonds ); ++num_hbonds; } } } /* uncorrected bond orders */ if( //(workspace->bond_mark[i] < 3 || workspace->bond_mark[j] < 3) && nbr_pj->d <= control->bond_cut && BOp( workspace, bonds, control->bo_cut, i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) { num_bonds += 2; ++btop_i; if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 ) workspace->bond_mark[j] = workspace->bond_mark[i] + 1; else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 ) { workspace->bond_mark[i] = workspace->bond_mark[j] + 1; } } } } Set_End_Index( i, btop_i, bonds ); if( local ) { H->end[i] = Htop; if( ihb == 1 ) Set_End_Index( atom_i->Hindex, ihb_top, hbonds ); } } workspace->realloc.Htop = Htop; workspace->realloc.num_bonds = num_bonds; workspace->realloc.num_hbonds = num_hbonds; Validate_Lists( system, workspace, lists, data->step, system->n, system->N, system->numH, comm ); } void Init_Forces_noQEq( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control, MPI_Comm comm ) { int i, j, pj; int start_i, end_i; int type_i, type_j; int btop_i, btop_j, num_bonds, num_hbonds; int ihb, jhb, ihb_top, jhb_top; int local, flag, renbr; - real r_ij, cutoff; + real cutoff; reax_list *far_nbrs, *bonds, *hbonds; single_body_parameters *sbp_i, *sbp_j; two_body_parameters *twbp; far_neighbor_data *nbr_pj; reax_atom *atom_i, *atom_j; far_nbrs = *lists + FAR_NBRS; bonds = *lists + BONDS; hbonds = *lists + HBONDS; for( i = 0; i < system->n; ++i ) workspace->bond_mark[i] = 0; for( i = system->n; i < system->N; ++i ) { workspace->bond_mark[i] = 1000; // put ghost atoms to an infinite distance } num_bonds = 0; num_hbonds = 0; btop_i = btop_j = 0; renbr = (data->step-data->prev_steps) % control->reneighbor == 0; for( i = 0; i < system->N; ++i ) { atom_i = &(system->my_atoms[i]); type_i = atom_i->type; if (type_i < 0) continue; start_i = Start_Index(i, far_nbrs); end_i = End_Index(i, far_nbrs); btop_i = End_Index( i, bonds ); sbp_i = &(system->reax_param.sbp[type_i]); if( i < system->n ) { local = 1; cutoff = MAX( control->hbond_cut, control->bond_cut ); } else { local = 0; cutoff = control->bond_cut; } ihb = -1; ihb_top = -1; if( local && control->hbond_cut > 0 ) { ihb = sbp_i->p_hbond; if( ihb == 1 ) ihb_top = End_Index( atom_i->Hindex, hbonds ); else ihb_top = -1; } /* update i-j distance - check if j is within cutoff */ for( pj = start_i; pj < end_i; ++pj ) { nbr_pj = &( far_nbrs->select.far_nbr_list[pj] ); j = nbr_pj->nbr; atom_j = &(system->my_atoms[j]); if( renbr ) { if( nbr_pj->d <= cutoff ) flag = 1; else flag = 0; } else{ nbr_pj->dvec[0] = atom_j->x[0] - atom_i->x[0]; nbr_pj->dvec[1] = atom_j->x[1] - atom_i->x[1]; nbr_pj->dvec[2] = atom_j->x[2] - atom_i->x[2]; nbr_pj->d = rvec_Norm_Sqr( nbr_pj->dvec ); if( nbr_pj->d <= SQR(cutoff) ) { nbr_pj->d = sqrt(nbr_pj->d); flag = 1; } else { flag = 0; } } if( flag ) { type_j = atom_j->type; if (type_j < 0) continue; - r_ij = nbr_pj->d; sbp_j = &(system->reax_param.sbp[type_j]); twbp = &(system->reax_param.tbp[type_i][type_j]); if( local ) { /* hydrogen bond lists */ if( control->hbond_cut > 0 && (ihb==1 || ihb==2) && nbr_pj->d <= control->hbond_cut ) { // fprintf( stderr, "%d %d\n", atom1, atom2 ); jhb = sbp_j->p_hbond; if( ihb == 1 && jhb == 2 ) { hbonds->select.hbond_list[ihb_top].nbr = j; hbonds->select.hbond_list[ihb_top].scl = 1; hbonds->select.hbond_list[ihb_top].ptr = nbr_pj; ++ihb_top; ++num_hbonds; } else if( j < system->n && ihb == 2 && jhb == 1 ) { jhb_top = End_Index( atom_j->Hindex, hbonds ); hbonds->select.hbond_list[jhb_top].nbr = i; hbonds->select.hbond_list[jhb_top].scl = -1; hbonds->select.hbond_list[jhb_top].ptr = nbr_pj; Set_End_Index( atom_j->Hindex, jhb_top+1, hbonds ); ++num_hbonds; } } } if( //(workspace->bond_mark[i] < 3 || workspace->bond_mark[j] < 3) && nbr_pj->d <= control->bond_cut && BOp( workspace, bonds, control->bo_cut, i , btop_i, nbr_pj, sbp_i, sbp_j, twbp ) ) { num_bonds += 2; ++btop_i; if( workspace->bond_mark[j] > workspace->bond_mark[i] + 1 ) workspace->bond_mark[j] = workspace->bond_mark[i] + 1; else if( workspace->bond_mark[i] > workspace->bond_mark[j] + 1 ) { workspace->bond_mark[i] = workspace->bond_mark[j] + 1; } } } } Set_End_Index( i, btop_i, bonds ); if( local && ihb == 1 ) Set_End_Index( atom_i->Hindex, ihb_top, hbonds ); } workspace->realloc.num_bonds = num_bonds; workspace->realloc.num_hbonds = num_hbonds; Validate_Lists( system, workspace, lists, data->step, system->n, system->N, system->numH, comm ); } void Estimate_Storages( reax_system *system, control_params *control, reax_list **lists, int *Htop, int *hb_top, int *bond_top, int *num_3body, MPI_Comm comm ) { int i, j, pj; int start_i, end_i; int type_i, type_j; int ihb, jhb; int local; real cutoff; - real r_ij, r2; + real r_ij; real C12, C34, C56; real BO, BO_s, BO_pi, BO_pi2; reax_list *far_nbrs; single_body_parameters *sbp_i, *sbp_j; two_body_parameters *twbp; far_neighbor_data *nbr_pj; reax_atom *atom_i, *atom_j; int mincap = system->mincap; double safezone = system->safezone; double saferzone = system->saferzone; far_nbrs = *lists + FAR_NBRS; *Htop = 0; memset( hb_top, 0, sizeof(int) * system->local_cap ); memset( bond_top, 0, sizeof(int) * system->total_cap ); *num_3body = 0; for( i = 0; i < system->N; ++i ) { atom_i = &(system->my_atoms[i]); type_i = atom_i->type; if (type_i < 0) continue; start_i = Start_Index(i, far_nbrs); end_i = End_Index(i, far_nbrs); sbp_i = &(system->reax_param.sbp[type_i]); if( i < system->n ) { local = 1; cutoff = control->nonb_cut; ++(*Htop); ihb = sbp_i->p_hbond; } else { local = 0; cutoff = control->bond_cut; ihb = -1; } for( pj = start_i; pj < end_i; ++pj ) { nbr_pj = &( far_nbrs->select.far_nbr_list[pj] ); j = nbr_pj->nbr; atom_j = &(system->my_atoms[j]); if(nbr_pj->d <= cutoff) { type_j = system->my_atoms[j].type; if (type_j < 0) continue; r_ij = nbr_pj->d; sbp_j = &(system->reax_param.sbp[type_j]); twbp = &(system->reax_param.tbp[type_i][type_j]); if( local ) { if( j < system->n || atom_i->orig_id < atom_j->orig_id ) //tryQEq ||1 ++(*Htop); /* hydrogen bond lists */ if( control->hbond_cut > 0.1 && (ihb==1 || ihb==2) && nbr_pj->d <= control->hbond_cut ) { jhb = sbp_j->p_hbond; if( ihb == 1 && jhb == 2 ) ++hb_top[i]; else if( j < system->n && ihb == 2 && jhb == 1 ) ++hb_top[j]; } } /* uncorrected bond orders */ if( nbr_pj->d <= control->bond_cut ) { - r2 = SQR(r_ij); - if( sbp_i->r_s > 0.0 && sbp_j->r_s > 0.0) { C12 = twbp->p_bo1 * pow( r_ij / twbp->r_s, twbp->p_bo2 ); BO_s = (1.0 + control->bo_cut) * exp( C12 ); } else BO_s = C12 = 0.0; if( sbp_i->r_pi > 0.0 && sbp_j->r_pi > 0.0) { C34 = twbp->p_bo3 * pow( r_ij / twbp->r_p, twbp->p_bo4 ); BO_pi = exp( C34 ); } else BO_pi = C34 = 0.0; if( sbp_i->r_pi_pi > 0.0 && sbp_j->r_pi_pi > 0.0) { C56 = twbp->p_bo5 * pow( r_ij / twbp->r_pp, twbp->p_bo6 ); BO_pi2= exp( C56 ); } else BO_pi2 = C56 = 0.0; /* Initially BO values are the uncorrected ones, page 1 */ BO = BO_s + BO_pi + BO_pi2; if( BO >= control->bo_cut ) { ++bond_top[i]; ++bond_top[j]; } } } } } *Htop = (int)(MAX( *Htop * safezone, mincap * MIN_HENTRIES )); for( i = 0; i < system->n; ++i ) hb_top[i] = (int)(MAX( hb_top[i] * saferzone, MIN_HBONDS )); for( i = 0; i < system->N; ++i ) { *num_3body += SQR(bond_top[i]); bond_top[i] = MAX( bond_top[i] * 2, MIN_BONDS ); } } void Compute_Forces( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control, mpi_datatypes *mpi_data ) { MPI_Comm comm; int qeq_flag; comm = mpi_data->world; qeq_flag = 0; if( qeq_flag ) Init_Forces( system, control, data, workspace, lists, out_control, comm ); else Init_Forces_noQEq( system, control, data, workspace, lists, out_control, comm ); /********* bonded interactions ************/ Compute_Bonded_Forces( system, control, data, workspace, lists, out_control, mpi_data->world ); /********* nonbonded interactions ************/ Compute_NonBonded_Forces( system, control, data, workspace, lists, out_control, mpi_data->world ); /*********** total force ***************/ Compute_Total_Force( system, control, data, workspace, lists, mpi_data ); } diff --git a/src/USER-REAXC/reaxc_hydrogen_bonds.cpp b/src/USER-REAXC/reaxc_hydrogen_bonds.cpp index b366872b7..b51ac6a18 100644 --- a/src/USER-REAXC/reaxc_hydrogen_bonds.cpp +++ b/src/USER-REAXC/reaxc_hydrogen_bonds.cpp @@ -1,185 +1,184 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_hydrogen_bonds.h" #include "reaxc_bond_orders.h" #include "reaxc_list.h" #include "reaxc_valence_angles.h" #include "reaxc_vector.h" void Hydrogen_Bonds( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control ) { int i, j, k, pi, pk; int type_i, type_j, type_k; int start_j, end_j, hb_start_j, hb_end_j; int hblist[MAX_BONDS]; int itr, top; int num_hb_intrs = 0; ivec rel_jk; - real r_ij, r_jk, theta, cos_theta, sin_xhz4, cos_xhz1, sin_theta2; + real r_jk, theta, cos_theta, sin_xhz4, cos_xhz1, sin_theta2; real e_hb, exp_hb2, exp_hb3, CEhb1, CEhb2, CEhb3; rvec dcos_theta_di, dcos_theta_dj, dcos_theta_dk; rvec dvec_jk, force, ext_press; hbond_parameters *hbp; bond_order_data *bo_ij; bond_data *pbond_ij; far_neighbor_data *nbr_jk; reax_list *bonds, *hbonds; bond_data *bond_list; hbond_data *hbond_list; // tally variables real fi_tmp[3], fk_tmp[3], delij[3], delkj[3]; bonds = (*lists) + BONDS; bond_list = bonds->select.bond_list; hbonds = (*lists) + HBONDS; hbond_list = hbonds->select.hbond_list; for( j = 0; j < system->n; ++j ) if (system->my_atoms[j].type < 0) continue; if( system->reax_param.sbp[system->my_atoms[j].type].p_hbond == 1 ) { type_j = system->my_atoms[j].type; start_j = Start_Index(j, bonds); end_j = End_Index(j, bonds); hb_start_j = Start_Index( system->my_atoms[j].Hindex, hbonds ); hb_end_j = End_Index( system->my_atoms[j].Hindex, hbonds ); top = 0; for( pi = start_j; pi < end_j; ++pi ) { pbond_ij = &( bond_list[pi] ); i = pbond_ij->nbr; type_i = system->my_atoms[i].type; if (type_i < 0) continue; bo_ij = &(pbond_ij->bo_data); if( system->reax_param.sbp[type_i].p_hbond == 2 && bo_ij->BO >= HB_THRESHOLD ) hblist[top++] = pi; } for( pk = hb_start_j; pk < hb_end_j; ++pk ) { /* set k's varibles */ k = hbond_list[pk].nbr; type_k = system->my_atoms[k].type; if (type_k < 0) continue; nbr_jk = hbond_list[pk].ptr; r_jk = nbr_jk->d; rvec_Scale( dvec_jk, hbond_list[pk].scl, nbr_jk->dvec ); for( itr = 0; itr < top; ++itr ) { pi = hblist[itr]; pbond_ij = &( bonds->select.bond_list[pi] ); i = pbond_ij->nbr; if( system->my_atoms[i].orig_id != system->my_atoms[k].orig_id ) { bo_ij = &(pbond_ij->bo_data); type_i = system->my_atoms[i].type; if (type_i < 0) continue; - r_ij = pbond_ij->d; hbp = &(system->reax_param.hbp[ type_i ][ type_j ][ type_k ]); ++num_hb_intrs; Calculate_Theta( pbond_ij->dvec, pbond_ij->d, dvec_jk, r_jk, &theta, &cos_theta ); /* the derivative of cos(theta) */ Calculate_dCos_Theta( pbond_ij->dvec, pbond_ij->d, dvec_jk, r_jk, &dcos_theta_di, &dcos_theta_dj, &dcos_theta_dk ); /* hyrogen bond energy*/ sin_theta2 = sin( theta/2.0 ); sin_xhz4 = SQR(sin_theta2); sin_xhz4 *= sin_xhz4; cos_xhz1 = ( 1.0 - cos_theta ); exp_hb2 = exp( -hbp->p_hb2 * bo_ij->BO ); exp_hb3 = exp( -hbp->p_hb3 * ( hbp->r0_hb / r_jk + r_jk / hbp->r0_hb - 2.0 ) ); data->my_en.e_hb += e_hb = hbp->p_hb1 * (1.0 - exp_hb2) * exp_hb3 * sin_xhz4; CEhb1 = hbp->p_hb1 * hbp->p_hb2 * exp_hb2 * exp_hb3 * sin_xhz4; CEhb2 = -hbp->p_hb1/2.0 * (1.0 - exp_hb2) * exp_hb3 * cos_xhz1; CEhb3 = -hbp->p_hb3 * (-hbp->r0_hb / SQR(r_jk) + 1.0 / hbp->r0_hb) * e_hb; /* hydrogen bond forces */ bo_ij->Cdbo += CEhb1; // dbo term if( control->virial == 0 ) { // dcos terms rvec_ScaledAdd( workspace->f[i], +CEhb2, dcos_theta_di ); rvec_ScaledAdd( workspace->f[j], +CEhb2, dcos_theta_dj ); rvec_ScaledAdd( workspace->f[k], +CEhb2, dcos_theta_dk ); // dr terms rvec_ScaledAdd( workspace->f[j], -CEhb3/r_jk, dvec_jk ); rvec_ScaledAdd( workspace->f[k], +CEhb3/r_jk, dvec_jk ); } else { rvec_Scale( force, +CEhb2, dcos_theta_di ); // dcos terms rvec_Add( workspace->f[i], force ); rvec_iMultiply( ext_press, pbond_ij->rel_box, force ); rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press ); rvec_ScaledAdd( workspace->f[j], +CEhb2, dcos_theta_dj ); ivec_Scale( rel_jk, hbond_list[pk].scl, nbr_jk->rel_box ); rvec_Scale( force, +CEhb2, dcos_theta_dk ); rvec_Add( workspace->f[k], force ); rvec_iMultiply( ext_press, rel_jk, force ); rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press ); // dr terms rvec_ScaledAdd( workspace->f[j], -CEhb3/r_jk, dvec_jk ); rvec_Scale( force, CEhb3/r_jk, dvec_jk ); rvec_Add( workspace->f[k], force ); rvec_iMultiply( ext_press, rel_jk, force ); rvec_ScaledAdd( data->my_ext_press, 1.0, ext_press ); } /* tally into per-atom virials */ if (system->pair_ptr->vflag_atom || system->pair_ptr->evflag) { rvec_ScaledSum( delij, 1., system->my_atoms[i].x, -1., system->my_atoms[j].x ); rvec_ScaledSum( delkj, 1., system->my_atoms[k].x, -1., system->my_atoms[j].x ); rvec_Scale(fi_tmp, CEhb2, dcos_theta_di); rvec_Scale(fk_tmp, CEhb2, dcos_theta_dk); rvec_ScaledAdd(fk_tmp, CEhb3/r_jk, dvec_jk); system->pair_ptr->ev_tally3(i,j,k,e_hb,0.0,fi_tmp,fk_tmp,delij,delkj); } } } } } } diff --git a/src/USER-REAXC/reaxc_init_md.cpp b/src/USER-REAXC/reaxc_init_md.cpp index df1a85702..a674b2e39 100644 --- a/src/USER-REAXC/reaxc_init_md.cpp +++ b/src/USER-REAXC/reaxc_init_md.cpp @@ -1,282 +1,280 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_init_md.h" #include "reaxc_allocate.h" #include "reaxc_forces.h" #include "reaxc_io_tools.h" #include "reaxc_list.h" #include "reaxc_lookup.h" #include "reaxc_reset_tools.h" #include "reaxc_system_props.h" #include "reaxc_tool_box.h" #include "reaxc_vector.h" int Init_System( reax_system *system, control_params *control, char *msg ) { int i; reax_atom *atom; int mincap = system->mincap; double safezone = system->safezone; double saferzone = system->saferzone; // determine the local and total capacity system->local_cap = MAX( (int)(system->n * safezone), mincap); system->total_cap = MAX( (int)(system->N * safezone), mincap); /* estimate numH and Hcap */ system->numH = 0; if( control->hbond_cut > 0 ) for( i = 0; i < system->n; ++i ) { atom = &(system->my_atoms[i]); if (atom->type < 0) continue; if( system->reax_param.sbp[ atom->type ].p_hbond == 1 ) atom->Hindex = system->numH++; else atom->Hindex = -1; } system->Hcap = (int)(MAX( system->numH * saferzone, mincap )); return SUCCESS; } int Init_Simulation_Data( reax_system *system, control_params *control, simulation_data *data, char *msg ) { Reset_Simulation_Data( data, control->virial ); /* initialize the timer(s) */ if( system->my_rank == MASTER_NODE ) { data->timing.start = Get_Time( ); } data->step = data->prev_steps = 0; return SUCCESS; } void Init_Taper( control_params *control, storage *workspace, MPI_Comm comm ) { real d1, d7; real swa, swa2, swa3; real swb, swb2, swb3; swa = control->nonb_low; swb = control->nonb_cut; if( fabs( swa ) > 0.01 ) fprintf( stderr, "Warning: non-zero lower Taper-radius cutoff\n" ); if( swb < 0 ) { fprintf( stderr, "Negative upper Taper-radius cutoff\n" ); MPI_Abort( comm, INVALID_INPUT ); } else if( swb < 5 ) fprintf( stderr, "Warning: very low Taper-radius cutoff: %f\n", swb ); d1 = swb - swa; d7 = pow( d1, 7.0 ); swa2 = SQR( swa ); swa3 = CUBE( swa ); swb2 = SQR( swb ); swb3 = CUBE( swb ); workspace->Tap[7] = 20.0 / d7; workspace->Tap[6] = -70.0 * (swa + swb) / d7; workspace->Tap[5] = 84.0 * (swa2 + 3.0*swa*swb + swb2) / d7; workspace->Tap[4] = -35.0 * (swa3 + 9.0*swa2*swb + 9.0*swa*swb2 + swb3 ) / d7; workspace->Tap[3] = 140.0 * (swa3*swb + 3.0*swa2*swb2 + swa*swb3 ) / d7; workspace->Tap[2] =-210.0 * (swa3*swb2 + swa2*swb3) / d7; workspace->Tap[1] = 140.0 * swa3 * swb3 / d7; workspace->Tap[0] = (-35.0*swa3*swb2*swb2 + 21.0*swa2*swb3*swb2 + 7.0*swa*swb3*swb3 + swb3*swb3*swb ) / d7; } int Init_Workspace( reax_system *system, control_params *control, storage *workspace, MPI_Comm comm, char *msg ) { int ret; ret = Allocate_Workspace( system, control, workspace, system->local_cap, system->total_cap, comm, msg ); if( ret != SUCCESS ) return ret; memset( &(workspace->realloc), 0, sizeof(reallocate_data) ); Reset_Workspace( system, workspace ); /* Initialize the Taper function */ Init_Taper( control, workspace, comm ); return SUCCESS; } /************** setup communication data structures **************/ int Init_MPI_Datatypes( reax_system *system, storage *workspace, mpi_datatypes *mpi_data, MPI_Comm comm, char *msg ) { /* setup the world */ mpi_data->world = comm; MPI_Comm_size( comm, &(system->wsize) ); return SUCCESS; } int Init_Lists( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, mpi_datatypes *mpi_data, char *msg ) { - int i, num_nbrs; - int total_hbonds, total_bonds, bond_cap, num_3body, cap_3body, Htop; + int i, total_hbonds, total_bonds, bond_cap, num_3body, cap_3body, Htop; int *hb_top, *bond_top; - int nrecv[MAX_NBRS]; MPI_Comm comm; int mincap = system->mincap; double safezone = system->safezone; double saferzone = system->saferzone; comm = mpi_data->world; bond_top = (int*) calloc( system->total_cap, sizeof(int) ); hb_top = (int*) calloc( system->local_cap, sizeof(int) ); Estimate_Storages( system, control, lists, &Htop, hb_top, bond_top, &num_3body, comm ); if( control->hbond_cut > 0 ) { /* init H indexes */ total_hbonds = 0; for( i = 0; i < system->n; ++i ) { system->my_atoms[i].num_hbonds = hb_top[i]; total_hbonds += hb_top[i]; } total_hbonds = (int)(MAX( total_hbonds*saferzone, mincap*MIN_HBONDS )); if( !Make_List( system->Hcap, total_hbonds, TYP_HBOND, *lists+HBONDS, comm ) ) { fprintf( stderr, "not enough space for hbonds list. terminating!\n" ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } } total_bonds = 0; for( i = 0; i < system->N; ++i ) { system->my_atoms[i].num_bonds = bond_top[i]; total_bonds += bond_top[i]; } bond_cap = (int)(MAX( total_bonds*safezone, mincap*MIN_BONDS )); if( !Make_List( system->total_cap, bond_cap, TYP_BOND, *lists+BONDS, comm ) ) { fprintf( stderr, "not enough space for bonds list. terminating!\n" ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } /* 3bodies list */ cap_3body = (int)(MAX( num_3body*safezone, MIN_3BODIES )); if( !Make_List( bond_cap, cap_3body, TYP_THREE_BODY, *lists+THREE_BODIES, comm ) ){ fprintf( stderr, "Problem in initializing angles list. Terminating!\n" ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } free( hb_top ); free( bond_top ); return SUCCESS; } void Initialize( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control, mpi_datatypes *mpi_data, MPI_Comm comm ) { char msg[MAX_STR]; if( Init_MPI_Datatypes(system, workspace, mpi_data, comm, msg) == FAILURE ) { fprintf( stderr, "p%d: init_mpi_datatypes: could not create datatypes\n", system->my_rank ); fprintf( stderr, "p%d: mpi_data couldn't be initialized! terminating.\n", system->my_rank ); MPI_Abort( mpi_data->world, CANNOT_INITIALIZE ); } if( Init_System(system, control, msg) == FAILURE ){ fprintf( stderr, "p%d: %s\n", system->my_rank, msg ); fprintf( stderr, "p%d: system could not be initialized! terminating.\n", system->my_rank ); MPI_Abort( mpi_data->world, CANNOT_INITIALIZE ); } if( Init_Simulation_Data( system, control, data, msg ) == FAILURE ) { fprintf( stderr, "p%d: %s\n", system->my_rank, msg ); fprintf( stderr, "p%d: sim_data couldn't be initialized! terminating.\n", system->my_rank ); MPI_Abort( mpi_data->world, CANNOT_INITIALIZE ); } if( Init_Workspace( system, control, workspace, mpi_data->world, msg ) == FAILURE ) { fprintf( stderr, "p%d:init_workspace: not enough memory\n", system->my_rank ); fprintf( stderr, "p%d:workspace couldn't be initialized! terminating.\n", system->my_rank ); MPI_Abort( mpi_data->world, CANNOT_INITIALIZE ); } if( Init_Lists( system, control, data, workspace, lists, mpi_data, msg ) == FAILURE ) { fprintf( stderr, "p%d: %s\n", system->my_rank, msg ); fprintf( stderr, "p%d: system could not be initialized! terminating.\n", system->my_rank ); MPI_Abort( mpi_data->world, CANNOT_INITIALIZE ); } if( Init_Output_Files(system,control,out_control,mpi_data,msg)== FAILURE) { fprintf( stderr, "p%d: %s\n", system->my_rank, msg ); fprintf( stderr, "p%d: could not open output files! terminating...\n", system->my_rank ); MPI_Abort( mpi_data->world, CANNOT_INITIALIZE ); } if( control->tabulate ) { if( Init_Lookup_Tables( system, control, workspace, mpi_data, msg ) == FAILURE ) { fprintf( stderr, "p%d: %s\n", system->my_rank, msg ); fprintf( stderr, "p%d: couldn't create lookup table! terminating.\n", system->my_rank ); MPI_Abort( mpi_data->world, CANNOT_INITIALIZE ); } } Init_Force_Functions( control ); } diff --git a/src/USER-REAXC/reaxc_io_tools.cpp b/src/USER-REAXC/reaxc_io_tools.cpp index 9645234bd..513b59c9f 100644 --- a/src/USER-REAXC/reaxc_io_tools.cpp +++ b/src/USER-REAXC/reaxc_io_tools.cpp @@ -1,582 +1,581 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "update.h" #include "reaxc_io_tools.h" -#include "reaxc_basic_comm.h" #include "reaxc_list.h" #include "reaxc_reset_tools.h" #include "reaxc_system_props.h" #include "reaxc_tool_box.h" #include "reaxc_traj.h" #include "reaxc_vector.h" print_interaction Print_Interactions[NUM_INTRS]; int Init_Output_Files( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes *mpi_data, char *msg ) { char temp[MAX_STR]; int ret; if( out_control->write_steps > 0 ){ ret = Init_Traj( system, control, out_control, mpi_data, msg ); if( ret == FAILURE ) return ret; } if( system->my_rank == MASTER_NODE ) { /* These files are written only by the master node */ if( out_control->energy_update_freq > 0 ) { /* init potentials file */ sprintf( temp, "%s.pot", control->sim_name ); if( (out_control->pot = fopen( temp, "w" )) != NULL ) { fflush( out_control->pot ); } else { strcpy( msg, "init_out_controls: .pot file could not be opened\n" ); return FAILURE; } /* init log file */ } /* init pressure file */ if( control->ensemble == NPT || control->ensemble == iNPT || control->ensemble == sNPT ) { sprintf( temp, "%s.prs", control->sim_name ); if( (out_control->prs = fopen( temp, "w" )) != NULL ) { fprintf(out_control->prs,"%8s%13s%13s%13s%13s%13s%13s%13s\n", "step", "Pint/norm[x]", "Pint/norm[y]", "Pint/norm[z]", "Pext/Ptot[x]", "Pext/Ptot[y]", "Pext/Ptot[z]", "Pkin/V" ); fflush( out_control->prs ); } else { strcpy(msg,"init_out_controls: .prs file couldn't be opened\n"); return FAILURE; } } } return SUCCESS; } /************************ close output files ************************/ int Close_Output_Files( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes *mpi_data ) { if( out_control->write_steps > 0 ) End_Traj( system->my_rank, out_control ); if( system->my_rank == MASTER_NODE ) { if( out_control->energy_update_freq > 0 ) { fclose( out_control->pot ); } if( control->ensemble == NPT || control->ensemble == iNPT || control->ensemble == sNPT ) fclose( out_control->prs ); } return SUCCESS; } void Print_Box( simulation_box* box, char *name, FILE *out ) { // int i, j; fprintf( out, "%s:\n", name ); fprintf( out, "\tmin[%8.3f %8.3f %8.3f]\n", box->min[0], box->min[1], box->min[2] ); fprintf( out, "\tmax[%8.3f %8.3f %8.3f]\n", box->max[0], box->max[1], box->max[2] ); fprintf( out, "\tdims[%8.3f%8.3f%8.3f]\n", box->box_norms[0], box->box_norms[1], box->box_norms[2] ); } void Print_Grid( grid* g, FILE *out ) { int x, y, z, gc_type; ivec gc_str; char gcell_type_text[10][12] = { "NO_NBRS", "NEAR_ONLY", "HBOND_ONLY", "FAR_ONLY", "NEAR_HBOND", "NEAR_FAR", "HBOND_FAR", "FULL_NBRS", "NATIVE" }; fprintf( out, "\tnumber of grid cells: %d %d %d\n", g->ncells[0], g->ncells[1], g->ncells[2] ); fprintf( out, "\tgcell lengths: %8.3f %8.3f %8.3f\n", g->cell_len[0], g->cell_len[1], g->cell_len[2] ); fprintf( out, "\tinverses of gcell lengths: %8.3f %8.3f %8.3f\n", g->inv_len[0], g->inv_len[1], g->inv_len[2] ); fprintf( out, "\t---------------------------------\n" ); fprintf( out, "\tnumber of native gcells: %d %d %d\n", g->native_cells[0], g->native_cells[1], g->native_cells[2] ); fprintf( out, "\tnative gcell span: %d-%d %d-%d %d-%d\n", g->native_str[0], g->native_end[0], g->native_str[1], g->native_end[1], g->native_str[2], g->native_end[2] ); fprintf( out, "\t---------------------------------\n" ); fprintf( out, "\tvlist gcell stretch: %d %d %d\n", g->vlist_span[0], g->vlist_span[1], g->vlist_span[2] ); fprintf( out, "\tnonbonded nbrs gcell stretch: %d %d %d\n", g->nonb_span[0], g->nonb_span[1], g->nonb_span[2] ); fprintf( out, "\tbonded nbrs gcell stretch: %d %d %d\n", g->bond_span[0], g->bond_span[1], g->bond_span[2] ); fprintf( out, "\t---------------------------------\n" ); fprintf( out, "\tghost gcell span: %d %d %d\n", g->ghost_span[0], g->ghost_span[1], g->ghost_span[2] ); fprintf( out, "\tnonbonded ghost gcell span: %d %d %d\n", g->ghost_nonb_span[0],g->ghost_nonb_span[1],g->ghost_nonb_span[2]); fprintf(out, "\thbonded ghost gcell span: %d %d %d\n", g->ghost_hbond_span[0],g->ghost_hbond_span[1],g->ghost_hbond_span[2]); fprintf( out, "\tbonded ghost gcell span: %d %d %d\n", g->ghost_bond_span[0],g->ghost_bond_span[1],g->ghost_bond_span[2]); fprintf( out, "\t---------------------------------\n" ); fprintf( stderr, "GCELL MARKS:\n" ); gc_type = g->cells[0][0][0].type; ivec_MakeZero( gc_str ); x = y = z = 0; for( x = 0; x < g->ncells[0]; ++x ) for( y = 0; y < g->ncells[1]; ++y ) for( z = 0; z < g->ncells[2]; ++z ) if( g->cells[x][y][z].type != gc_type ){ fprintf( stderr, "\tgcells from(%2d %2d %2d) to (%2d %2d %2d): %d - %s\n", gc_str[0], gc_str[1], gc_str[2], x, y, z, gc_type, gcell_type_text[gc_type] ); gc_type = g->cells[x][y][z].type; gc_str[0] = x; gc_str[1] = y; gc_str[2] = z; } fprintf( stderr, "\tgcells from(%2d %2d %2d) to (%2d %2d %2d): %d - %s\n", gc_str[0], gc_str[1], gc_str[2], x, y, z, gc_type, gcell_type_text[gc_type] ); fprintf( out, "-------------------------------------\n" ); } void Print_Native_GCells( reax_system *system ) { int i, j, k, l; char fname[100]; FILE *f; grid *g; grid_cell *gc; char gcell_type_text[10][12] = { "NO_NBRS", "NEAR_ONLY", "HBOND_ONLY", "FAR_ONLY", "NEAR_HBOND", "NEAR_FAR", "HBOND_FAR", "FULL_NBRS", "NATIVE" }; sprintf( fname, "native_gcells.%d", system->my_rank ); f = fopen( fname, "w" ); g = &(system->my_grid); for( i = g->native_str[0]; i < g->native_end[0]; i++ ) for( j = g->native_str[1]; j < g->native_end[1]; j++ ) for( k = g->native_str[2]; k < g->native_end[2]; k++ ) { gc = &( g->cells[i][j][k] ); fprintf( f, "p%d gcell(%2d %2d %2d) of type %d(%s)\n", system->my_rank, i, j, k, gc->type, gcell_type_text[gc->type] ); fprintf( f, "\tatom list start: %d, end: %d\n\t", gc->str, gc->end ); for( l = gc->str; l < gc->end; ++l ) fprintf( f, TAGINT_FORMAT, system->my_atoms[l].orig_id ); fprintf( f, "\n" ); } fclose(f); } void Print_All_GCells( reax_system *system ) { int i, j, k, l; char fname[100]; FILE *f; grid *g; grid_cell *gc; char gcell_type_text[10][12] = { "NO_NBRS", "NEAR_ONLY", "HBOND_ONLY", "FAR_ONLY", "NEAR_HBOND", "NEAR_FAR", "HBOND_FAR", "FULL_NBRS", "NATIVE" }; sprintf( fname, "all_gcells.%d", system->my_rank ); f = fopen( fname, "w" ); g = &(system->my_grid); for( i = 0; i < g->ncells[0]; i++ ) for( j = 0; j < g->ncells[1]; j++ ) for( k = 0; k < g->ncells[2]; k++ ) { gc = &( g->cells[i][j][k] ); fprintf( f, "p%d gcell(%2d %2d %2d) of type %d(%s)\n", system->my_rank, i, j, k, gc->type, gcell_type_text[gc->type] ); fprintf( f, "\tatom list start: %d, end: %d\n\t", gc->str, gc->end ); for( l = gc->str; l < gc->end; ++l ) fprintf( f, TAGINT_FORMAT, system->my_atoms[l].orig_id ); fprintf( f, "\n" ); } fclose(f); } void Print_My_Atoms( reax_system *system ) { int i; char fname[100]; FILE *fh; sprintf( fname, "my_atoms.%d", system->my_rank ); if( (fh = fopen( fname, "w" )) == NULL ) { fprintf( stderr, "error in opening my_atoms file" ); MPI_Abort( MPI_COMM_WORLD, FILE_NOT_FOUND ); } for( i = 0; i < system->n; ++i ) fprintf( fh, "p%-2d %-5d %2d %24.15e%24.15e%24.15e\n", system->my_rank, system->my_atoms[i].orig_id, system->my_atoms[i].type, system->my_atoms[i].x[0], system->my_atoms[i].x[1], system->my_atoms[i].x[2] ); fclose( fh ); } void Print_My_Ext_Atoms( reax_system *system ) { int i; char fname[100]; FILE *fh; sprintf( fname, "my_ext_atoms.%d", system->my_rank ); if( (fh = fopen( fname, "w" )) == NULL ) { fprintf( stderr, "error in opening my_ext_atoms file" ); MPI_Abort( MPI_COMM_WORLD, FILE_NOT_FOUND ); } for( i = 0; i < system->N; ++i ) fprintf( fh, "p%-2d %-5d imprt%-5d %2d %24.15e%24.15e%24.15e\n", system->my_rank, system->my_atoms[i].orig_id, system->my_atoms[i].imprt_id, system->my_atoms[i].type, system->my_atoms[i].x[0], system->my_atoms[i].x[1], system->my_atoms[i].x[2] ); fclose( fh ); } void Print_Far_Neighbors( reax_system *system, reax_list **lists, control_params *control ) { char fname[100]; int i, j, nbr, natoms; rc_tagint id_i, id_j; FILE *fout; reax_list *far_nbrs; sprintf( fname, "%s.far_nbrs.%d", control->sim_name, system->my_rank ); fout = fopen( fname, "w" ); far_nbrs = (*lists) + FAR_NBRS; natoms = system->N; for( i = 0; i < natoms; ++i ) { id_i = system->my_atoms[i].orig_id; for( j = Start_Index(i,far_nbrs); j < End_Index(i,far_nbrs); ++j ) { nbr = far_nbrs->select.far_nbr_list[j].nbr; id_j = system->my_atoms[nbr].orig_id; fprintf( fout, "%6d%6d%24.15e%24.15e%24.15e%24.15e\n", id_i, id_j, far_nbrs->select.far_nbr_list[j].d, far_nbrs->select.far_nbr_list[j].dvec[0], far_nbrs->select.far_nbr_list[j].dvec[1], far_nbrs->select.far_nbr_list[j].dvec[2] ); fprintf( fout, "%6d%6d%24.15e%24.15e%24.15e%24.15e\n", id_j, id_i, far_nbrs->select.far_nbr_list[j].d, -far_nbrs->select.far_nbr_list[j].dvec[0], -far_nbrs->select.far_nbr_list[j].dvec[1], -far_nbrs->select.far_nbr_list[j].dvec[2] ); } } fclose( fout ); } void Print_Sparse_Matrix( reax_system *system, sparse_matrix *A ) { int i, j; for( i = 0; i < A->n; ++i ) for( j = A->start[i]; j < A->end[i]; ++j ) fprintf( stderr, "%d %d %.15e\n", system->my_atoms[i].orig_id, system->my_atoms[A->entries[j].j].orig_id, A->entries[j].val ); } void Print_Sparse_Matrix2( reax_system *system, sparse_matrix *A, char *fname ) { int i, j; FILE *f = fopen( fname, "w" ); for( i = 0; i < A->n; ++i ) for( j = A->start[i]; j < A->end[i]; ++j ) fprintf( f, "%d %d %.15e\n", system->my_atoms[i].orig_id, system->my_atoms[A->entries[j].j].orig_id, A->entries[j].val ); fclose(f); } void Print_Symmetric_Sparse(reax_system *system, sparse_matrix *A, char *fname) { int i, j; reax_atom *ai, *aj; FILE *f = fopen( fname, "w" ); for( i = 0; i < A->n; ++i ) { ai = &(system->my_atoms[i]); for( j = A->start[i]; j < A->end[i]; ++j ) { aj = &(system->my_atoms[A->entries[j].j]); fprintf( f, "%d %d %.15e\n", ai->renumber, aj->renumber, A->entries[j].val ); if( A->entries[j].j < system->n && ai->renumber != aj->renumber ) fprintf( f, "%d %d %.15e\n", aj->renumber, ai->renumber, A->entries[j].val ); } } fclose(f); } void Print_Linear_System( reax_system *system, control_params *control, storage *workspace, int step ) { int i; char fname[100]; reax_atom *ai; FILE *out; // print rhs and init guesses for QEq sprintf( fname, "%s.p%dstate%d", control->sim_name, system->my_rank, step ); out = fopen( fname, "w" ); for( i = 0; i < system->n; i++ ) { ai = &(system->my_atoms[i]); fprintf( out, "%6d%2d%24.15e%24.15e%24.15e%24.15e%24.15e%24.15e%24.15e\n", ai->renumber, ai->type, ai->x[0], ai->x[1], ai->x[2], workspace->s[i], workspace->b_s[i], workspace->t[i], workspace->b_t[i] ); } fclose( out ); // print QEq coef matrix sprintf( fname, "%s.p%dH%d", control->sim_name, system->my_rank, step ); Print_Symmetric_Sparse( system, workspace->H, fname ); } void Print_LinSys_Soln( reax_system *system, real *x, real *b_prm, real *b ) { int i; char fname[100]; FILE *fout; sprintf( fname, "qeq.%d.out", system->my_rank ); fout = fopen( fname, "w" ); for( i = 0; i < system->n; ++i ) fprintf( fout, "%6d%10.4f%10.4f%10.4f\n", system->my_atoms[i].orig_id, x[i], b_prm[i], b[i] ); fclose( fout ); } void Print_Charges( reax_system *system ) { int i; char fname[100]; FILE *fout; sprintf( fname, "q.%d.out", system->my_rank ); fout = fopen( fname, "w" ); for( i = 0; i < system->n; ++i ) fprintf( fout, "%6d %10.7f %10.7f %10.7f\n", system->my_atoms[i].orig_id, system->my_atoms[i].s[0], system->my_atoms[i].t[0], system->my_atoms[i].q ); fclose( fout ); } void Print_Bonds( reax_system *system, reax_list *bonds, char *fname ) { int i, j, pj; bond_data *pbond; bond_order_data *bo_ij; FILE *f = fopen( fname, "w" ); for( i = 0; i < system->N; ++i ) for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { pbond = &(bonds->select.bond_list[pj]); bo_ij = &(pbond->bo_data); j = pbond->nbr; fprintf( f, "%8d%8d %24.15f %24.15f\n", i, j,//system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, pbond->d, bo_ij->BO ); } fclose(f); } int fn_qsort_intcmp( const void *a, const void *b ) { return( *(int *)a - *(int *)b ); } void Print_Bond_List2( reax_system *system, reax_list *bonds, char *fname ) { int i,j, nbr, pj; rc_tagint id_i, id_j; FILE *f = fopen( fname, "w" ); int temp[500]; int num=0; for( i = 0; i < system->n; ++i ) { num=0; id_i = system->my_atoms[i].orig_id; fprintf( f, "%6d:", id_i); for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { nbr = bonds->select.bond_list[pj].nbr; id_j = system->my_atoms[nbr].orig_id; if( id_i < id_j ) temp[num++] = id_j; } qsort(&temp, num, sizeof(int), fn_qsort_intcmp); for(j=0; j < num; j++) fprintf(f, "%6d", temp[j] ); fprintf(f, "\n"); } } void Print_Total_Force( reax_system *system, simulation_data *data, storage *workspace ) { int i; fprintf( stderr, "step: %d\n", data->step ); fprintf( stderr, "%6s\t%-38s\n", "atom", "atom.f[0,1,2]"); for( i = 0; i < system->N; ++i ) fprintf( stderr, "%6d %f %f %f\n", //"%6d%24.15e%24.15e%24.15e\n", system->my_atoms[i].orig_id, workspace->f[i][0], workspace->f[i][1], workspace->f[i][2] ); } void Output_Results( reax_system *system, control_params *control, simulation_data *data, reax_list **lists, output_controls *out_control, mpi_datatypes *mpi_data ) { if((out_control->energy_update_freq > 0 && data->step%out_control->energy_update_freq == 0) || (out_control->write_steps > 0 && data->step%out_control->write_steps == 0)){ /* update system-wide energies */ Compute_System_Energy( system, data, mpi_data->world ); /* output energies */ if( system->my_rank == MASTER_NODE && out_control->energy_update_freq > 0 && data->step % out_control->energy_update_freq == 0 ) { if( control->virial ){ fprintf( out_control->prs, "%8d%13.6f%13.6f%13.6f%13.6f%13.6f%13.6f%13.6f\n", data->step, data->int_press[0], data->int_press[1], data->int_press[2], data->ext_press[0], data->ext_press[1], data->ext_press[2], data->kin_press ); fprintf( out_control->prs, "%8s%13.6f%13.6f%13.6f%13.6f%13.6f%13.6f%13.6f\n", "",system->big_box.box_norms[0], system->big_box.box_norms[1], system->big_box.box_norms[2], data->tot_press[0], data->tot_press[1], data->tot_press[2], system->big_box.V ); fflush( out_control->prs); } } /* write current frame */ if( out_control->write_steps > 0 && (data->step-data->prev_steps) % out_control->write_steps == 0 ) { Append_Frame( system, control, data, lists, out_control, mpi_data ); } } } diff --git a/src/USER-REAXC/reaxc_multi_body.cpp b/src/USER-REAXC/reaxc_multi_body.cpp index 220fcb072..f1b56ef5d 100644 --- a/src/USER-REAXC/reaxc_multi_body.cpp +++ b/src/USER-REAXC/reaxc_multi_body.cpp @@ -1,243 +1,240 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_multi_body.h" #include "reaxc_bond_orders.h" #include "reaxc_list.h" #include "reaxc_vector.h" void Atom_Energy( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control ) { int i, j, pj, type_i, type_j; real Delta_lpcorr, dfvl; real e_lp, expvd2, inv_expvd2, dElp, CElp, DlpVi; real e_lph, Di, vov3, deahu2dbo, deahu2dsbo; real e_ov, CEover1, CEover2, CEover3, CEover4; real exp_ovun1, exp_ovun2, sum_ovun1, sum_ovun2; real exp_ovun2n, exp_ovun6, exp_ovun8; real inv_exp_ovun1, inv_exp_ovun2, inv_exp_ovun2n, inv_exp_ovun8; real e_un, CEunder1, CEunder2, CEunder3, CEunder4; - real p_lp1, p_lp2, p_lp3; + real p_lp2, p_lp3; real p_ovun2, p_ovun3, p_ovun4, p_ovun5, p_ovun6, p_ovun7, p_ovun8; - real eng_tmp, f_tmp; + real eng_tmp; int numbonds; - single_body_parameters *sbp_i, *sbp_j; + single_body_parameters *sbp_i; two_body_parameters *twbp; bond_data *pbond; bond_order_data *bo_ij; reax_list *bonds = (*lists) + BONDS; /* Initialize parameters */ - p_lp1 = system->reax_param.gp.l[15]; p_lp3 = system->reax_param.gp.l[5]; p_ovun3 = system->reax_param.gp.l[32]; p_ovun4 = system->reax_param.gp.l[31]; p_ovun6 = system->reax_param.gp.l[6]; p_ovun7 = system->reax_param.gp.l[8]; p_ovun8 = system->reax_param.gp.l[9]; for( i = 0; i < system->n; ++i ) { /* set the parameter pointer */ type_i = system->my_atoms[i].type; if (type_i < 0) continue; sbp_i = &(system->reax_param.sbp[ type_i ]); /* lone-pair Energy */ p_lp2 = sbp_i->p_lp2; expvd2 = exp( -75 * workspace->Delta_lp[i] ); inv_expvd2 = 1. / (1. + expvd2 ); numbonds = 0; e_lp = 0.0; for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) numbonds ++; /* calculate the energy */ if (numbonds > 0) data->my_en.e_lp += e_lp = p_lp2 * workspace->Delta_lp[i] * inv_expvd2; dElp = p_lp2 * inv_expvd2 + 75 * p_lp2 * workspace->Delta_lp[i] * expvd2 * SQR(inv_expvd2); CElp = dElp * workspace->dDelta_lp[i]; if (numbonds > 0) workspace->CdDelta[i] += CElp; // lp - 1st term /* tally into per-atom energy */ if( system->pair_ptr->evflag) system->pair_ptr->ev_tally(i,i,system->n,1,e_lp,0.0,0.0,0.0,0.0,0.0); /* correction for C2 */ if( p_lp3 > 0.001 && !strcmp(system->reax_param.sbp[type_i].name, "C") ) for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { j = bonds->select.bond_list[pj].nbr; type_j = system->my_atoms[j].type; if (type_j < 0) continue; if( !strcmp( system->reax_param.sbp[type_j].name, "C" ) ) { twbp = &( system->reax_param.tbp[type_i][type_j]); bo_ij = &( bonds->select.bond_list[pj].bo_data ); Di = workspace->Delta[i]; vov3 = bo_ij->BO - Di - 0.040*pow(Di, 4.); if( vov3 > 3. ) { data->my_en.e_lp += e_lph = p_lp3 * SQR(vov3-3.0); deahu2dbo = 2.*p_lp3*(vov3 - 3.); deahu2dsbo = 2.*p_lp3*(vov3 - 3.)*(-1. - 0.16*pow(Di, 3.)); bo_ij->Cdbo += deahu2dbo; workspace->CdDelta[i] += deahu2dsbo; /* tally into per-atom energy */ if( system->pair_ptr->evflag) system->pair_ptr->ev_tally(i,j,system->n,1,e_lph,0.0,0.0,0.0,0.0,0.0); } } } } for( i = 0; i < system->n; ++i ) { type_i = system->my_atoms[i].type; if (type_i < 0) continue; sbp_i = &(system->reax_param.sbp[ type_i ]); /* over-coordination energy */ if( sbp_i->mass > 21.0 ) dfvl = 0.0; else dfvl = 1.0; // only for 1st-row elements p_ovun2 = sbp_i->p_ovun2; sum_ovun1 = sum_ovun2 = 0; for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { j = bonds->select.bond_list[pj].nbr; type_j = system->my_atoms[j].type; if (type_j < 0) continue; bo_ij = &(bonds->select.bond_list[pj].bo_data); - sbp_j = &(system->reax_param.sbp[ type_j ]); twbp = &(system->reax_param.tbp[ type_i ][ type_j ]); sum_ovun1 += twbp->p_ovun1 * twbp->De_s * bo_ij->BO; sum_ovun2 += (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j])* ( bo_ij->BO_pi + bo_ij->BO_pi2 ); } exp_ovun1 = p_ovun3 * exp( p_ovun4 * sum_ovun2 ); inv_exp_ovun1 = 1.0 / (1 + exp_ovun1); Delta_lpcorr = workspace->Delta[i] - (dfvl * workspace->Delta_lp_temp[i]) * inv_exp_ovun1; exp_ovun2 = exp( p_ovun2 * Delta_lpcorr ); inv_exp_ovun2 = 1.0 / (1.0 + exp_ovun2); DlpVi = 1.0 / (Delta_lpcorr + sbp_i->valency + 1e-8); CEover1 = Delta_lpcorr * DlpVi * inv_exp_ovun2; data->my_en.e_ov += e_ov = sum_ovun1 * CEover1; CEover2 = sum_ovun1 * DlpVi * inv_exp_ovun2 * (1.0 - Delta_lpcorr * ( DlpVi + p_ovun2 * exp_ovun2 * inv_exp_ovun2 )); CEover3 = CEover2 * (1.0 - dfvl * workspace->dDelta_lp[i] * inv_exp_ovun1 ); CEover4 = CEover2 * (dfvl * workspace->Delta_lp_temp[i]) * p_ovun4 * exp_ovun1 * SQR(inv_exp_ovun1); /* under-coordination potential */ p_ovun2 = sbp_i->p_ovun2; p_ovun5 = sbp_i->p_ovun5; exp_ovun2n = 1.0 / exp_ovun2; exp_ovun6 = exp( p_ovun6 * Delta_lpcorr ); exp_ovun8 = p_ovun7 * exp(p_ovun8 * sum_ovun2); inv_exp_ovun2n = 1.0 / (1.0 + exp_ovun2n); inv_exp_ovun8 = 1.0 / (1.0 + exp_ovun8); numbonds = 0; e_un = 0.0; for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) numbonds ++; if (numbonds > 0) data->my_en.e_un += e_un = -p_ovun5 * (1.0 - exp_ovun6) * inv_exp_ovun2n * inv_exp_ovun8; CEunder1 = inv_exp_ovun2n * ( p_ovun5 * p_ovun6 * exp_ovun6 * inv_exp_ovun8 + p_ovun2 * e_un * exp_ovun2n ); CEunder2 = -e_un * p_ovun8 * exp_ovun8 * inv_exp_ovun8; CEunder3 = CEunder1 * (1.0 - dfvl*workspace->dDelta_lp[i]*inv_exp_ovun1); CEunder4 = CEunder1 * (dfvl*workspace->Delta_lp_temp[i]) * p_ovun4 * exp_ovun1 * SQR(inv_exp_ovun1) + CEunder2; /* tally into per-atom energy */ if( system->pair_ptr->evflag) { eng_tmp = e_ov; if (numbonds > 0) eng_tmp += e_un; - f_tmp = CEover3 + CEunder3; system->pair_ptr->ev_tally(i,i,system->n,1,eng_tmp,0.0,0.0,0.0,0.0,0.0); } /* forces */ workspace->CdDelta[i] += CEover3; // OvCoor - 2nd term if (numbonds > 0) workspace->CdDelta[i] += CEunder3; // UnCoor - 1st term for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { pbond = &(bonds->select.bond_list[pj]); j = pbond->nbr; bo_ij = &(pbond->bo_data); twbp = &(system->reax_param.tbp[ system->my_atoms[i].type ] [system->my_atoms[pbond->nbr].type]); bo_ij->Cdbo += CEover1 * twbp->p_ovun1 * twbp->De_s;// OvCoor-1st workspace->CdDelta[j] += CEover4 * (1.0 - dfvl*workspace->dDelta_lp[j]) * (bo_ij->BO_pi + bo_ij->BO_pi2); // OvCoor-3a bo_ij->Cdbopi += CEover4 * (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // OvCoor-3b bo_ij->Cdbopi2 += CEover4 * (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // OvCoor-3b workspace->CdDelta[j] += CEunder4 * (1.0 - dfvl*workspace->dDelta_lp[j]) * (bo_ij->BO_pi + bo_ij->BO_pi2); // UnCoor - 2a bo_ij->Cdbopi += CEunder4 * (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // UnCoor-2b bo_ij->Cdbopi2 += CEunder4 * (workspace->Delta[j] - dfvl*workspace->Delta_lp_temp[j]); // UnCoor-2b } } } diff --git a/src/USER-REAXC/reaxc_tool_box.cpp b/src/USER-REAXC/reaxc_tool_box.cpp index 55feac209..7fccbb342 100644 --- a/src/USER-REAXC/reaxc_tool_box.cpp +++ b/src/USER-REAXC/reaxc_tool_box.cpp @@ -1,280 +1,240 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_tool_box.h" void Transform( rvec x1, simulation_box *box, char flag, rvec x2 ) { int i, j; real tmp; if (flag > 0) { for (i=0; i < 3; i++) { tmp = 0.0; for (j=0; j < 3; j++) tmp += box->trans[i][j]*x1[j]; x2[i] = tmp; } } else { for (i=0; i < 3; i++) { tmp = 0.0; for (j=0; j < 3; j++) tmp += box->trans_inv[i][j]*x1[j]; x2[i] = tmp; } } } void Transform_to_UnitBox( rvec x1, simulation_box *box, char flag, rvec x2 ) { Transform( x1, box, flag, x2 ); x2[0] /= box->box_norms[0]; x2[1] /= box->box_norms[1]; x2[2] /= box->box_norms[2]; } void Fit_to_Periodic_Box( simulation_box *box, rvec *p ) { int i; for( i = 0; i < 3; ++i ) { if( (*p)[i] < box->min[i] ) { /* handle lower coords */ while( (*p)[i] < box->min[i] ) (*p)[i] += box->box_norms[i]; } else if( (*p)[i] >= box->max[i] ) { /* handle higher coords */ while( (*p)[i] >= box->max[i] ) (*p)[i] -= box->box_norms[i]; } } } -/************** from geo_tools.c *****************/ -void Make_Point( real x, real y, real z, rvec* p ) -{ - (*p)[0] = x; - (*p)[1] = y; - (*p)[2] = z; -} - - - -int is_Valid_Serial( storage *workspace, int serial ) -{ - return SUCCESS; -} - - - -int Check_Input_Range( int val, int lo, int hi, char *message, MPI_Comm comm ) -{ - if( val < lo || val > hi ) { - fprintf( stderr, "%s\nInput %d - Out of range %d-%d. Terminating...\n", - message, val, lo, hi ); - MPI_Abort( comm, INVALID_INPUT ); - } - - return 1; -} - - -void Trim_Spaces( char *element ) -{ - int i, j; - - for( i = 0; element[i] == ' '; ++i ); // skip initial space chars - - for( j = i; j < (int)(strlen(element)) && element[j] != ' '; ++j ) - element[j-i] = toupper( element[j] ); // make uppercase, offset to 0 - element[j-i] = 0; // finalize the string -} - struct timeval tim; real t_end; real Get_Time( ) { gettimeofday(&tim, NULL ); return( tim.tv_sec + (tim.tv_usec / 1000000.0) ); } real Get_Timing_Info( real t_start ) { gettimeofday(&tim, NULL ); t_end = tim.tv_sec + (tim.tv_usec / 1000000.0); return (t_end - t_start); } void Update_Timing_Info( real *t_start, real *timing ) { gettimeofday(&tim, NULL ); t_end = tim.tv_sec + (tim.tv_usec / 1000000.0); *timing += (t_end - *t_start); *t_start = t_end; } int Get_Atom_Type( reax_interaction *reax_param, char *s, MPI_Comm comm ) { int i; for( i = 0; i < reax_param->num_atom_types; ++i ) if( !strcmp( reax_param->sbp[i].name, s ) ) return i; fprintf( stderr, "Unknown atom type %s. Terminating...\n", s ); MPI_Abort( comm, UNKNOWN_ATOM_TYPE ); return -1; } char *Get_Element( reax_system *system, int i ) { return &( system->reax_param.sbp[system->my_atoms[i].type].name[0] ); } char *Get_Atom_Name( reax_system *system, int i ) { return &(system->my_atoms[i].name[0]); } int Allocate_Tokenizer_Space( char **line, char **backup, char ***tokens ) { int i; if( (*line = (char*) malloc( sizeof(char) * MAX_LINE )) == NULL ) return FAILURE; if( (*backup = (char*) malloc( sizeof(char) * MAX_LINE )) == NULL ) return FAILURE; if( (*tokens = (char**) malloc( sizeof(char*) * MAX_TOKENS )) == NULL ) return FAILURE; for( i = 0; i < MAX_TOKENS; i++ ) if( ((*tokens)[i] = (char*) malloc(sizeof(char) * MAX_TOKEN_LEN)) == NULL ) return FAILURE; return SUCCESS; } int Tokenize( char* s, char*** tok ) { char test[MAX_LINE]; const char *sep = (const char *)"\t \n!="; char *word; int count=0; strncpy( test, s, MAX_LINE ); for( word = strtok(test, sep); word; word = strtok(NULL, sep) ) { strncpy( (*tok)[count], word, MAX_LINE ); count++; } return count; } /* safe malloc */ void *smalloc( long n, const char *name, MPI_Comm comm ) { void *ptr; if( n <= 0 ) { fprintf( stderr, "WARNING: trying to allocate %ld bytes for array %s. ", n, name ); fprintf( stderr, "returning NULL.\n" ); return NULL; } ptr = malloc( n ); if( ptr == NULL ) { fprintf( stderr, "ERROR: failed to allocate %ld bytes for array %s", n, name ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } return ptr; } /* safe calloc */ void *scalloc( int n, int size, const char *name, MPI_Comm comm ) { void *ptr; if( n <= 0 ) { fprintf( stderr, "WARNING: trying to allocate %d elements for array %s. ", n, name ); fprintf( stderr, "returning NULL.\n" ); return NULL; } if( size <= 0 ) { fprintf( stderr, "WARNING: elements size for array %s is %d. ", name, size ); fprintf( stderr, "returning NULL.\n" ); return NULL; } ptr = calloc( n, size ); if( ptr == NULL ) { fprintf( stderr, "ERROR: failed to allocate %d bytes for array %s", n*size, name ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } return ptr; } /* safe free */ void sfree( void *ptr, const char *name ) { if( ptr == NULL ) { fprintf( stderr, "WARNING: trying to free the already NULL pointer %s!\n", name ); return; } free( ptr ); ptr = NULL; } diff --git a/src/USER-REAXC/reaxc_tool_box.h b/src/USER-REAXC/reaxc_tool_box.h index 2ef27dd6d..d7784fc0d 100644 --- a/src/USER-REAXC/reaxc_tool_box.h +++ b/src/USER-REAXC/reaxc_tool_box.h @@ -1,74 +1,68 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #ifndef __TOOL_BOX_H_ #define __TOOL_BOX_H_ #include "reaxc_types.h" #include "reaxc_defs.h" /* from comm_tools.h */ int SumScan( int, int, int, MPI_Comm ); void SumScanB( int, int, int, int, MPI_Comm, int* ); /* from box.h */ void Transform_to_UnitBox( rvec, simulation_box*, char, rvec ); void Fit_to_Periodic_Box( simulation_box*, rvec* ); void Box_Touch_Point( simulation_box*, ivec, rvec ); int is_Inside_Box( simulation_box*, rvec ); int iown_midpoint( simulation_box*, rvec, rvec ); /* from grid.h */ void GridCell_Closest_Point( grid_cell*, grid_cell*, ivec, ivec, rvec ); void GridCell_to_Box_Points( grid_cell*, ivec, rvec, rvec ); real DistSqr_between_Special_Points( rvec, rvec ); real DistSqr_to_Special_Point( rvec, rvec ); int Relative_Coord_Encoding( ivec ); -/* from geo_tools.h */ -void Make_Point( real, real, real, rvec* ); -int is_Valid_Serial( storage*, int ); -int Check_Input_Range( int, int, int, char*, MPI_Comm ); -void Trim_Spaces( char* ); - /* from system_props.h */ real Get_Time( ); real Get_Timing_Info( real ); void Update_Timing_Info( real*, real* ); /* from io_tools.h */ int Get_Atom_Type( reax_interaction*, char*, MPI_Comm ); char *Get_Element( reax_system*, int ); char *Get_Atom_Name( reax_system*, int ); int Allocate_Tokenizer_Space( char**, char**, char*** ); int Tokenize( char*, char*** ); /* from lammps */ void *smalloc( long, const char*, MPI_Comm ); void *scalloc( int, int, const char*, MPI_Comm ); void sfree( void*, const char* ); #endif diff --git a/src/USER-REAXC/reaxc_torsion_angles.cpp b/src/USER-REAXC/reaxc_torsion_angles.cpp index 16f6a4539..223fd1d40 100644 --- a/src/USER-REAXC/reaxc_torsion_angles.cpp +++ b/src/USER-REAXC/reaxc_torsion_angles.cpp @@ -1,471 +1,469 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_torsion_angles.h" #include "reaxc_bond_orders.h" #include "reaxc_list.h" #include "reaxc_tool_box.h" #include "reaxc_vector.h" #define MIN_SINE 1e-10 real Calculate_Omega( rvec dvec_ij, real r_ij, rvec dvec_jk, real r_jk, rvec dvec_kl, real r_kl, rvec dvec_li, real r_li, three_body_interaction_data *p_ijk, three_body_interaction_data *p_jkl, rvec dcos_omega_di, rvec dcos_omega_dj, rvec dcos_omega_dk, rvec dcos_omega_dl, output_controls *out_control ) { real unnorm_cos_omega, unnorm_sin_omega, omega; real sin_ijk, cos_ijk, sin_jkl, cos_jkl; real htra, htrb, htrc, hthd, hthe, hnra, hnrc, hnhd, hnhe; real arg, poem, tel; rvec cross_jk_kl; sin_ijk = sin( p_ijk->theta ); cos_ijk = cos( p_ijk->theta ); sin_jkl = sin( p_jkl->theta ); cos_jkl = cos( p_jkl->theta ); /* omega */ unnorm_cos_omega = -rvec_Dot(dvec_ij, dvec_jk) * rvec_Dot(dvec_jk, dvec_kl) + SQR( r_jk ) * rvec_Dot( dvec_ij, dvec_kl ); rvec_Cross( cross_jk_kl, dvec_jk, dvec_kl ); unnorm_sin_omega = -r_jk * rvec_Dot( dvec_ij, cross_jk_kl ); omega = atan2( unnorm_sin_omega, unnorm_cos_omega ); htra = r_ij + cos_ijk * ( r_kl * cos_jkl - r_jk ); htrb = r_jk - r_ij * cos_ijk - r_kl * cos_jkl; htrc = r_kl + cos_jkl * ( r_ij * cos_ijk - r_jk ); hthd = r_ij * sin_ijk * ( r_jk - r_kl * cos_jkl ); hthe = r_kl * sin_jkl * ( r_jk - r_ij * cos_ijk ); hnra = r_kl * sin_ijk * sin_jkl; hnrc = r_ij * sin_ijk * sin_jkl; hnhd = r_ij * r_kl * cos_ijk * sin_jkl; hnhe = r_ij * r_kl * sin_ijk * cos_jkl; poem = 2.0 * r_ij * r_kl * sin_ijk * sin_jkl; if( poem < 1e-20 ) poem = 1e-20; tel = SQR( r_ij ) + SQR( r_jk ) + SQR( r_kl ) - SQR( r_li ) - 2.0 * ( r_ij * r_jk * cos_ijk - r_ij * r_kl * cos_ijk * cos_jkl + r_jk * r_kl * cos_jkl ); arg = tel / poem; if( arg > 1.0 ) arg = 1.0; if( arg < -1.0 ) arg = -1.0; if( sin_ijk >= 0 && sin_ijk <= MIN_SINE ) sin_ijk = MIN_SINE; else if( sin_ijk <= 0 && sin_ijk >= -MIN_SINE ) sin_ijk = -MIN_SINE; if( sin_jkl >= 0 && sin_jkl <= MIN_SINE ) sin_jkl = MIN_SINE; else if( sin_jkl <= 0 && sin_jkl >= -MIN_SINE ) sin_jkl = -MIN_SINE; // dcos_omega_di rvec_ScaledSum( dcos_omega_di, (htra-arg*hnra)/r_ij, dvec_ij, -1., dvec_li ); rvec_ScaledAdd( dcos_omega_di,-(hthd-arg*hnhd)/sin_ijk, p_ijk->dcos_dk ); rvec_Scale( dcos_omega_di, 2.0 / poem, dcos_omega_di ); // dcos_omega_dj rvec_ScaledSum( dcos_omega_dj,-(htra-arg*hnra)/r_ij, dvec_ij, -htrb / r_jk, dvec_jk ); rvec_ScaledAdd( dcos_omega_dj,-(hthd-arg*hnhd)/sin_ijk, p_ijk->dcos_dj ); rvec_ScaledAdd( dcos_omega_dj,-(hthe-arg*hnhe)/sin_jkl, p_jkl->dcos_di ); rvec_Scale( dcos_omega_dj, 2.0 / poem, dcos_omega_dj ); // dcos_omega_dk rvec_ScaledSum( dcos_omega_dk,-(htrc-arg*hnrc)/r_kl, dvec_kl, htrb / r_jk, dvec_jk ); rvec_ScaledAdd( dcos_omega_dk,-(hthd-arg*hnhd)/sin_ijk, p_ijk->dcos_di ); rvec_ScaledAdd( dcos_omega_dk,-(hthe-arg*hnhe)/sin_jkl, p_jkl->dcos_dj ); rvec_Scale( dcos_omega_dk, 2.0 / poem, dcos_omega_dk ); // dcos_omega_dl rvec_ScaledSum( dcos_omega_dl, (htrc-arg*hnrc)/r_kl, dvec_kl, 1., dvec_li ); rvec_ScaledAdd( dcos_omega_dl,-(hthe-arg*hnhe)/sin_jkl, p_jkl->dcos_dk ); rvec_Scale( dcos_omega_dl, 2.0 / poem, dcos_omega_dl ); return omega; } void Torsion_Angles( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control ) { int i, j, k, l, pi, pj, pk, pl, pij, plk, natoms; int type_i, type_j, type_k, type_l; - int start_j, end_j, start_k, end_k; + int start_j, end_j; int start_pj, end_pj, start_pk, end_pk; int num_frb_intrs = 0; real Delta_j, Delta_k; real r_ij, r_jk, r_kl, r_li; real BOA_ij, BOA_jk, BOA_kl; real exp_tor2_ij, exp_tor2_jk, exp_tor2_kl; real exp_tor1, exp_tor3_DjDk, exp_tor4_DjDk, exp_tor34_inv; real exp_cot2_jk, exp_cot2_ij, exp_cot2_kl; real fn10, f11_DjDk, dfn11, fn12; real theta_ijk, theta_jkl; real sin_ijk, sin_jkl; real cos_ijk, cos_jkl; real tan_ijk_i, tan_jkl_i; real omega, cos_omega, cos2omega, cos3omega; rvec dcos_omega_di, dcos_omega_dj, dcos_omega_dk, dcos_omega_dl; real CV, cmn, CEtors1, CEtors2, CEtors3, CEtors4; real CEtors5, CEtors6, CEtors7, CEtors8, CEtors9; real Cconj, CEconj1, CEconj2, CEconj3; real CEconj4, CEconj5, CEconj6; real e_tor, e_con; rvec dvec_li; rvec force, ext_press; ivec rel_box_jl; // rtensor total_rtensor, temp_rtensor; four_body_header *fbh; four_body_parameters *fbp; bond_data *pbond_ij, *pbond_jk, *pbond_kl; bond_order_data *bo_ij, *bo_jk, *bo_kl; three_body_interaction_data *p_ijk, *p_jkl; real p_tor2 = system->reax_param.gp.l[23]; real p_tor3 = system->reax_param.gp.l[24]; real p_tor4 = system->reax_param.gp.l[25]; real p_cot2 = system->reax_param.gp.l[27]; reax_list *bonds = (*lists) + BONDS; reax_list *thb_intrs = (*lists) + THREE_BODIES; // Virial tallying variables real delil[3], deljl[3], delkl[3]; - real eng_tmp, f_scaler, fi_tmp[3], fj_tmp[3], fk_tmp[3]; + real eng_tmp, fi_tmp[3], fj_tmp[3], fk_tmp[3]; natoms = system->n; for( j = 0; j < natoms; ++j ) { type_j = system->my_atoms[j].type; Delta_j = workspace->Delta_boc[j]; start_j = Start_Index(j, bonds); end_j = End_Index(j, bonds); for( pk = start_j; pk < end_j; ++pk ) { pbond_jk = &( bonds->select.bond_list[pk] ); k = pbond_jk->nbr; bo_jk = &( pbond_jk->bo_data ); BOA_jk = bo_jk->BO - control->thb_cut; if( system->my_atoms[j].orig_id < system->my_atoms[k].orig_id && bo_jk->BO > control->thb_cut/*0*/ && Num_Entries(pk, thb_intrs) ) { - start_k = Start_Index(k, bonds); - end_k = End_Index(k, bonds); pj = pbond_jk->sym_index; // pj points to j on k's list if( Num_Entries(pj, thb_intrs) ) { type_k = system->my_atoms[k].type; Delta_k = workspace->Delta_boc[k]; r_jk = pbond_jk->d; start_pk = Start_Index(pk, thb_intrs ); end_pk = End_Index(pk, thb_intrs ); start_pj = Start_Index(pj, thb_intrs ); end_pj = End_Index(pj, thb_intrs ); exp_tor2_jk = exp( -p_tor2 * BOA_jk ); exp_cot2_jk = exp( -p_cot2 * SQR(BOA_jk - 1.5) ); exp_tor3_DjDk = exp( -p_tor3 * (Delta_j + Delta_k) ); exp_tor4_DjDk = exp( p_tor4 * (Delta_j + Delta_k) ); exp_tor34_inv = 1.0 / (1.0 + exp_tor3_DjDk + exp_tor4_DjDk); f11_DjDk = (2.0 + exp_tor3_DjDk) * exp_tor34_inv; for( pi = start_pk; pi < end_pk; ++pi ) { p_ijk = &( thb_intrs->select.three_body_list[pi] ); pij = p_ijk->pthb; // pij is pointer to i on j's bond_list pbond_ij = &( bonds->select.bond_list[pij] ); bo_ij = &( pbond_ij->bo_data ); if( bo_ij->BO > control->thb_cut/*0*/ ) { i = p_ijk->thb; type_i = system->my_atoms[i].type; r_ij = pbond_ij->d; BOA_ij = bo_ij->BO - control->thb_cut; theta_ijk = p_ijk->theta; sin_ijk = sin( theta_ijk ); cos_ijk = cos( theta_ijk ); //tan_ijk_i = 1. / tan( theta_ijk ); if( sin_ijk >= 0 && sin_ijk <= MIN_SINE ) tan_ijk_i = cos_ijk / MIN_SINE; else if( sin_ijk <= 0 && sin_ijk >= -MIN_SINE ) tan_ijk_i = cos_ijk / -MIN_SINE; else tan_ijk_i = cos_ijk / sin_ijk; exp_tor2_ij = exp( -p_tor2 * BOA_ij ); exp_cot2_ij = exp( -p_cot2 * SQR(BOA_ij -1.5) ); for( pl = start_pj; pl < end_pj; ++pl ) { p_jkl = &( thb_intrs->select.three_body_list[pl] ); l = p_jkl->thb; plk = p_jkl->pthb; //pointer to l on k's bond_list! pbond_kl = &( bonds->select.bond_list[plk] ); bo_kl = &( pbond_kl->bo_data ); type_l = system->my_atoms[l].type; fbh = &(system->reax_param.fbp[type_i][type_j] [type_k][type_l]); fbp = &(system->reax_param.fbp[type_i][type_j] [type_k][type_l].prm[0]); if( i != l && fbh->cnt && bo_kl->BO > control->thb_cut/*0*/ && bo_ij->BO * bo_jk->BO * bo_kl->BO > control->thb_cut/*0*/ ){ ++num_frb_intrs; r_kl = pbond_kl->d; BOA_kl = bo_kl->BO - control->thb_cut; theta_jkl = p_jkl->theta; sin_jkl = sin( theta_jkl ); cos_jkl = cos( theta_jkl ); //tan_jkl_i = 1. / tan( theta_jkl ); if( sin_jkl >= 0 && sin_jkl <= MIN_SINE ) tan_jkl_i = cos_jkl / MIN_SINE; else if( sin_jkl <= 0 && sin_jkl >= -MIN_SINE ) tan_jkl_i = cos_jkl / -MIN_SINE; else tan_jkl_i = cos_jkl /sin_jkl; rvec_ScaledSum( dvec_li, 1., system->my_atoms[i].x, -1., system->my_atoms[l].x ); r_li = rvec_Norm( dvec_li ); /* omega and its derivative */ omega = Calculate_Omega( pbond_ij->dvec, r_ij, pbond_jk->dvec, r_jk, pbond_kl->dvec, r_kl, dvec_li, r_li, p_ijk, p_jkl, dcos_omega_di, dcos_omega_dj, dcos_omega_dk, dcos_omega_dl, out_control ); cos_omega = cos( omega ); cos2omega = cos( 2. * omega ); cos3omega = cos( 3. * omega ); /* end omega calculations */ /* torsion energy */ exp_tor1 = exp( fbp->p_tor1 * SQR(2.0 - bo_jk->BO_pi - f11_DjDk) ); exp_tor2_kl = exp( -p_tor2 * BOA_kl ); exp_cot2_kl = exp( -p_cot2 * SQR(BOA_kl - 1.5) ); fn10 = (1.0 - exp_tor2_ij) * (1.0 - exp_tor2_jk) * (1.0 - exp_tor2_kl); CV = 0.5 * ( fbp->V1 * (1.0 + cos_omega) + fbp->V2 * exp_tor1 * (1.0 - cos2omega) + fbp->V3 * (1.0 + cos3omega) ); data->my_en.e_tor += e_tor = fn10 * sin_ijk * sin_jkl * CV; dfn11 = (-p_tor3 * exp_tor3_DjDk + (p_tor3 * exp_tor3_DjDk - p_tor4 * exp_tor4_DjDk) * (2.0 + exp_tor3_DjDk) * exp_tor34_inv) * exp_tor34_inv; CEtors1 = sin_ijk * sin_jkl * CV; CEtors2 = -fn10 * 2.0 * fbp->p_tor1 * fbp->V2 * exp_tor1 * (2.0 - bo_jk->BO_pi - f11_DjDk) * (1.0 - SQR(cos_omega)) * sin_ijk * sin_jkl; CEtors3 = CEtors2 * dfn11; CEtors4 = CEtors1 * p_tor2 * exp_tor2_ij * (1.0 - exp_tor2_jk) * (1.0 - exp_tor2_kl); CEtors5 = CEtors1 * p_tor2 * (1.0 - exp_tor2_ij) * exp_tor2_jk * (1.0 - exp_tor2_kl); CEtors6 = CEtors1 * p_tor2 * (1.0 - exp_tor2_ij) * (1.0 - exp_tor2_jk) * exp_tor2_kl; cmn = -fn10 * CV; CEtors7 = cmn * sin_jkl * tan_ijk_i; CEtors8 = cmn * sin_ijk * tan_jkl_i; CEtors9 = fn10 * sin_ijk * sin_jkl * (0.5 * fbp->V1 - 2.0 * fbp->V2 * exp_tor1 * cos_omega + 1.5 * fbp->V3 * (cos2omega + 2.0 * SQR(cos_omega))); /* end of torsion energy */ /* 4-body conjugation energy */ fn12 = exp_cot2_ij * exp_cot2_jk * exp_cot2_kl; data->my_en.e_con += e_con = fbp->p_cot1 * fn12 * (1.0 + (SQR(cos_omega) - 1.0) * sin_ijk * sin_jkl); Cconj = -2.0 * fn12 * fbp->p_cot1 * p_cot2 * (1.0 + (SQR(cos_omega) - 1.0) * sin_ijk * sin_jkl); CEconj1 = Cconj * (BOA_ij - 1.5e0); CEconj2 = Cconj * (BOA_jk - 1.5e0); CEconj3 = Cconj * (BOA_kl - 1.5e0); CEconj4 = -fbp->p_cot1 * fn12 * (SQR(cos_omega) - 1.0) * sin_jkl * tan_ijk_i; CEconj5 = -fbp->p_cot1 * fn12 * (SQR(cos_omega) - 1.0) * sin_ijk * tan_jkl_i; CEconj6 = 2.0 * fbp->p_cot1 * fn12 * cos_omega * sin_ijk * sin_jkl; /* end 4-body conjugation energy */ /* forces */ bo_jk->Cdbopi += CEtors2; workspace->CdDelta[j] += CEtors3; workspace->CdDelta[k] += CEtors3; bo_ij->Cdbo += (CEtors4 + CEconj1); bo_jk->Cdbo += (CEtors5 + CEconj2); bo_kl->Cdbo += (CEtors6 + CEconj3); if( control->virial == 0 ) { /* dcos_theta_ijk */ rvec_ScaledAdd( workspace->f[i], CEtors7 + CEconj4, p_ijk->dcos_dk ); rvec_ScaledAdd( workspace->f[j], CEtors7 + CEconj4, p_ijk->dcos_dj ); rvec_ScaledAdd( workspace->f[k], CEtors7 + CEconj4, p_ijk->dcos_di ); /* dcos_theta_jkl */ rvec_ScaledAdd( workspace->f[j], CEtors8 + CEconj5, p_jkl->dcos_di ); rvec_ScaledAdd( workspace->f[k], CEtors8 + CEconj5, p_jkl->dcos_dj ); rvec_ScaledAdd( workspace->f[l], CEtors8 + CEconj5, p_jkl->dcos_dk ); /* dcos_omega */ rvec_ScaledAdd( workspace->f[i], CEtors9 + CEconj6, dcos_omega_di ); rvec_ScaledAdd( workspace->f[j], CEtors9 + CEconj6, dcos_omega_dj ); rvec_ScaledAdd( workspace->f[k], CEtors9 + CEconj6, dcos_omega_dk ); rvec_ScaledAdd( workspace->f[l], CEtors9 + CEconj6, dcos_omega_dl ); } else { ivec_Sum(rel_box_jl, pbond_jk->rel_box, pbond_kl->rel_box); /* dcos_theta_ijk */ rvec_Scale( force, CEtors7 + CEconj4, p_ijk->dcos_dk ); rvec_Add( workspace->f[i], force ); rvec_iMultiply( ext_press, pbond_ij->rel_box, force ); rvec_Add( data->my_ext_press, ext_press ); rvec_ScaledAdd( workspace->f[j], CEtors7 + CEconj4, p_ijk->dcos_dj ); rvec_Scale( force, CEtors7 + CEconj4, p_ijk->dcos_di ); rvec_Add( workspace->f[k], force ); rvec_iMultiply( ext_press, pbond_jk->rel_box, force ); rvec_Add( data->my_ext_press, ext_press ); /* dcos_theta_jkl */ rvec_ScaledAdd( workspace->f[j], CEtors8 + CEconj5, p_jkl->dcos_di ); rvec_Scale( force, CEtors8 + CEconj5, p_jkl->dcos_dj ); rvec_Add( workspace->f[k], force ); rvec_iMultiply( ext_press, pbond_jk->rel_box, force ); rvec_Add( data->my_ext_press, ext_press ); rvec_Scale( force, CEtors8 + CEconj5, p_jkl->dcos_dk ); rvec_Add( workspace->f[l], force ); rvec_iMultiply( ext_press, rel_box_jl, force ); rvec_Add( data->my_ext_press, ext_press ); /* dcos_omega */ rvec_Scale( force, CEtors9 + CEconj6, dcos_omega_di ); rvec_Add( workspace->f[i], force ); rvec_iMultiply( ext_press, pbond_ij->rel_box, force ); rvec_Add( data->my_ext_press, ext_press ); rvec_ScaledAdd( workspace->f[j], CEtors9 + CEconj6, dcos_omega_dj ); rvec_Scale( force, CEtors9 + CEconj6, dcos_omega_dk ); rvec_Add( workspace->f[k], force ); rvec_iMultiply( ext_press, pbond_jk->rel_box, force ); rvec_Add( data->my_ext_press, ext_press ); rvec_Scale( force, CEtors9 + CEconj6, dcos_omega_dl ); rvec_Add( workspace->f[l], force ); rvec_iMultiply( ext_press, rel_box_jl, force ); rvec_Add( data->my_ext_press, ext_press ); } /* tally into per-atom virials */ if( system->pair_ptr->vflag_atom || system->pair_ptr->evflag) { // acquire vectors rvec_ScaledSum( delil, 1., system->my_atoms[l].x, -1., system->my_atoms[i].x ); rvec_ScaledSum( deljl, 1., system->my_atoms[l].x, -1., system->my_atoms[j].x ); rvec_ScaledSum( delkl, 1., system->my_atoms[l].x, -1., system->my_atoms[k].x ); // dcos_theta_ijk rvec_Scale( fi_tmp, CEtors7 + CEconj4, p_ijk->dcos_dk ); rvec_Scale( fj_tmp, CEtors7 + CEconj4, p_ijk->dcos_dj ); rvec_Scale( fk_tmp, CEtors7 + CEconj4, p_ijk->dcos_di ); // dcos_theta_jkl rvec_ScaledAdd( fj_tmp, CEtors8 + CEconj5, p_jkl->dcos_di ); rvec_ScaledAdd( fk_tmp, CEtors8 + CEconj5, p_jkl->dcos_dj ); // dcos_omega rvec_ScaledAdd( fi_tmp, CEtors9 + CEconj6, dcos_omega_di ); rvec_ScaledAdd( fj_tmp, CEtors9 + CEconj6, dcos_omega_dj ); rvec_ScaledAdd( fk_tmp, CEtors9 + CEconj6, dcos_omega_dk ); // tally eng_tmp = e_tor + e_con; if( system->pair_ptr->evflag) system->pair_ptr->ev_tally(j,k,natoms,1,eng_tmp,0.0,0.0,0.0,0.0,0.0); if( system->pair_ptr->vflag_atom) system->pair_ptr->v_tally4(i,j,k,l,fi_tmp,fj_tmp,fk_tmp,delil,deljl,delkl); } } // pl check ends } // pl loop ends } // pi check ends } // pi loop ends } // k-j neighbor check ends } // j<k && j-k neighbor check ends } // pk loop ends } // j loop } diff --git a/src/USER-REAXC/reaxc_traj.cpp b/src/USER-REAXC/reaxc_traj.cpp index 3a94ed45e..05bf73a29 100644 --- a/src/USER-REAXC/reaxc_traj.cpp +++ b/src/USER-REAXC/reaxc_traj.cpp @@ -1,779 +1,778 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_traj.h" #include "reaxc_list.h" #include "reaxc_tool_box.h" int Reallocate_Output_Buffer( output_controls *out_control, int req_space, MPI_Comm comm ) { if( out_control->buffer_len > 0 ) free( out_control->buffer ); out_control->buffer_len = (int)(req_space*SAFE_ZONE); out_control->buffer = (char*) malloc(out_control->buffer_len*sizeof(char)); if( out_control->buffer == NULL ) { fprintf( stderr, "insufficient memory for required buffer size %d. terminating!\n", (int) (req_space*SAFE_ZONE) ); MPI_Abort( comm, INSUFFICIENT_MEMORY ); } return SUCCESS; } void Write_Skip_Line( output_controls *out_control, mpi_datatypes *mpi_data, int my_rank, int skip, int num_section ) { if( my_rank == MASTER_NODE ) fprintf( out_control->strj, INT2_LINE, "chars_to_skip_section:", skip, num_section ); - } int Write_Header( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes *mpi_data ) { int num_hdr_lines, my_hdr_lines, buffer_req; char ensembles[ens_N][25] = { "NVE", "NVT", "fully flexible NPT", "semi isotropic NPT", "isotropic NPT" }; char reposition[3][25] = { "fit to periodic box", "CoM to center of box", "CoM to origin" }; char t_regime[3][25] = { "T-coupling only", "step-wise", "constant slope" }; char traj_methods[TF_N][10] = { "custom", "xyz" }; char atom_formats[8][40] = { "none", "invalid", "invalid", "invalid", "xyz_q", "xyz_q_fxfyfz", "xyz_q_vxvyvz", "detailed_atom_info" }; char bond_formats[3][30] = { "none", "basic_bond_info", "detailed_bond_info" }; char angle_formats[2][30] = { "none", "basic_angle_info" }; /* set header lengths */ num_hdr_lines = NUM_HEADER_LINES; my_hdr_lines = num_hdr_lines * ( system->my_rank == MASTER_NODE ); buffer_req = my_hdr_lines * HEADER_LINE_LEN; if( buffer_req > out_control->buffer_len * DANGER_ZONE ) Reallocate_Output_Buffer( out_control, buffer_req, mpi_data->world ); /* only the master node writes into trajectory header */ if( system->my_rank == MASTER_NODE ) { /* clear the contents of line & buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; /* to skip the header */ sprintf( out_control->line, INT_LINE, "chars_to_skip_header:", (num_hdr_lines-1) * HEADER_LINE_LEN ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* general simulation info */ sprintf( out_control->line, STR_LINE, "simulation_name:", out_control->traj_title ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "number_of_atoms:", system->bigN ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "ensemble_type:", ensembles[ control->ensemble ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "number_of_steps:", control->nsteps ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "timestep_length_(in_fs):", control->dt * 1000 ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* restart info */ sprintf( out_control->line, STR_LINE, "is_this_a_restart?:", (control->restart ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "write_restart_files?:", ((out_control->restart_freq > 0) ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "frequency_to_write_restarts:", out_control->restart_freq ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* preferences */ sprintf( out_control->line, STR_LINE, "tabulate_long_range_intrs?:", (control->tabulate ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "table_size:", control->tabulate ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "restrict_bonds?:", (control->restrict_bonds ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "bond_restriction_length:", control->restrict_bonds ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "reposition_atoms?:", reposition[control->reposition_atoms] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "remove_CoM_velocity?:", (control->ensemble==NVE) ? 0 : control->remove_CoM_vel); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* cut-off values */ sprintf( out_control->line, REAL_LINE, "bonded_intr_dist_cutoff:", control->bond_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "nonbonded_intr_dist_cutoff:", control->nonb_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "hbond_dist_cutoff:", control->hbond_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "reax_bond_threshold:", control->bo_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "physical_bond_threshold:", control->bg_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "valence_angle_threshold:", control->thb_cut ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, SCI_LINE, "QEq_tolerance:", control->q_err ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* temperature controls */ sprintf( out_control->line, REAL_LINE, "initial_temperature:", control->T_init ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "target_temperature:", control->T_final ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "thermal_inertia:", control->Tau_T ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "temperature_regime:", t_regime[ control->T_mode ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "temperature_change_rate_(K/ps):", control->T_rate / control->T_freq ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* pressure controls */ sprintf( out_control->line, REAL3_LINE, "target_pressure_(GPa):", control->P[0], control->P[1], control->P[2] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL3_LINE, "virial_inertia:", control->Tau_P[0], control->Tau_P[1], control->Tau_P[2] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* trajectory */ sprintf( out_control->line, INT_LINE, "energy_dumping_freq:", out_control->energy_update_freq ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "trajectory_dumping_freq:", out_control->write_steps ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "compress_trajectory_output?:", (out_control->traj_compress ? "yes" : "no") ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "trajectory_format:", traj_methods[ out_control->traj_method ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "atom_info:", atom_formats[ out_control->atom_info ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "bond_info:", bond_formats[ out_control->bond_info ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, STR_LINE, "angle_info:", angle_formats[ out_control->angle_info ] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* analysis */ //sprintf( out_control->line, STR_LINE, "molecular_analysis:", // (control->molec_anal ? "yes" : "no") ); //strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, INT_LINE, "molecular_analysis_frequency:", control->molecular_analysis ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); } /* dump out the buffer */ if( system->my_rank == MASTER_NODE ) fprintf( out_control->strj, "%s", out_control->buffer ); return SUCCESS; } int Write_Init_Desc( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes *mpi_data ) { int i, me, np, cnt, buffer_len, buffer_req; reax_atom *p_atom; //MPI_Request request; MPI_Status status; me = system->my_rank; np = system->wsize; /* skip info */ Write_Skip_Line( out_control, mpi_data, me, system->bigN * INIT_DESC_LEN, system->bigN ); if( out_control->traj_method == REG_TRAJ && me == MASTER_NODE ) buffer_req = system->bigN * INIT_DESC_LEN + 1; else buffer_req = system->n * INIT_DESC_LEN + 1; if( buffer_req > out_control->buffer_len * DANGER_ZONE ) Reallocate_Output_Buffer( out_control, buffer_req, mpi_data->world ); out_control->line[0] = 0; out_control->buffer[0] = 0; for( i = 0; i < system->n; ++i ) { p_atom = &( system->my_atoms[i] ); sprintf( out_control->line, INIT_DESC, p_atom->orig_id, p_atom->type, p_atom->name, system->reax_param.sbp[ p_atom->type ].mass ); strncpy( out_control->buffer + i*INIT_DESC_LEN, out_control->line, INIT_DESC_LEN+1 ); } if( me != MASTER_NODE ) MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np * INIT_DESCS + me, mpi_data->world ); else{ buffer_len = system->n * INIT_DESC_LEN; for( i = 0; i < np; ++i ) if( i != MASTER_NODE ) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*INIT_DESCS+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Init_Traj( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes *mpi_data, char *msg ) { char fname[MAX_STR]; int atom_line_len[ NR_OPT_ATOM ] = { 0, 0, 0, 0, ATOM_BASIC_LEN, ATOM_wV_LEN, ATOM_wF_LEN, ATOM_FULL_LEN }; int bond_line_len[ NR_OPT_BOND ] = { 0, BOND_BASIC_LEN, BOND_FULL_LEN }; int angle_line_len[ NR_OPT_ANGLE ] = { 0, ANGLE_BASIC_LEN }; /* generate trajectory name */ sprintf( fname, "%s.trj", control->sim_name ); /* how should I write atoms? */ out_control->atom_line_len = atom_line_len[ out_control->atom_info ]; out_control->write_atoms = ( out_control->atom_line_len ? 1 : 0 ); /* bonds? */ out_control->bond_line_len = bond_line_len[ out_control->bond_info ]; out_control->write_bonds = ( out_control->bond_line_len ? 1 : 0 ); /* angles? */ out_control->angle_line_len = angle_line_len[ out_control->angle_info ]; out_control->write_angles = ( out_control->angle_line_len ? 1 : 0 ); /* allocate line & buffer space */ out_control->line = (char*) calloc( MAX_TRJ_LINE_LEN + 1, sizeof(char) ); out_control->buffer_len = 0; out_control->buffer = NULL; /* write trajectory header and atom info, if applicable */ if( out_control->traj_method == REG_TRAJ) { if( system->my_rank == MASTER_NODE ) out_control->strj = fopen( fname, "w" ); } else { strcpy( msg, "init_traj: unknown trajectory option" ); return FAILURE; } Write_Header( system, control, out_control, mpi_data ); Write_Init_Desc( system, control, out_control, mpi_data ); return SUCCESS; } int Write_Frame_Header( reax_system *system, control_params *control, simulation_data *data, output_controls *out_control, mpi_datatypes *mpi_data ) { int me, num_frm_hdr_lines, my_frm_hdr_lines, buffer_req; me = system->my_rank; /* frame header lengths */ num_frm_hdr_lines = 22; my_frm_hdr_lines = num_frm_hdr_lines * ( me == MASTER_NODE ); buffer_req = my_frm_hdr_lines * HEADER_LINE_LEN; if( buffer_req > out_control->buffer_len * DANGER_ZONE ) Reallocate_Output_Buffer( out_control, buffer_req, mpi_data->world ); /* only the master node writes into trajectory header */ if( me == MASTER_NODE ) { /* clear the contents of line & buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; /* skip info */ sprintf( out_control->line, INT_LINE, "chars_to_skip_frame_header:", (num_frm_hdr_lines - 1) * HEADER_LINE_LEN ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* step & time */ sprintf( out_control->line, INT_LINE, "step:", data->step ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "time_in_ps:", data->step * control->dt ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* box info */ sprintf( out_control->line, REAL_LINE, "volume:", system->big_box.V ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL3_LINE, "box_dimensions:", system->big_box.box_norms[0], system->big_box.box_norms[1], system->big_box.box_norms[2] ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL3_LINE, "coordinate_angles:", 90.0, 90.0, 90.0 ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* system T and P */ sprintf( out_control->line, REAL_LINE, "temperature:", data->therm.T ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "pressure:", (control->ensemble==iNPT) ? data->iso_bar.P : data->flex_bar.P_scalar ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); /* energies */ sprintf( out_control->line, REAL_LINE, "total_energy:", data->sys_en.e_tot ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "total_kinetic:", data->sys_en.e_kin ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "total_potential:", data->sys_en.e_pot ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "bond_energy:", data->sys_en.e_bond ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "atom_energy:", data->sys_en.e_ov + data->sys_en.e_un ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "lone_pair_energy:", data->sys_en.e_lp ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "valence_angle_energy:", data->sys_en.e_ang + data->sys_en.e_pen ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "3-body_conjugation:", data->sys_en.e_coa ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "hydrogen_bond_energy:", data->sys_en.e_hb ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "torsion_angle_energy:", data->sys_en.e_tor ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "4-body_conjugation:", data->sys_en.e_con ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "vdWaals_energy:", data->sys_en.e_vdW ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "electrostatics_energy:", data->sys_en.e_ele ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); sprintf( out_control->line, REAL_LINE, "polarization_energy:", data->sys_en.e_pol ); strncat( out_control->buffer, out_control->line, HEADER_LINE_LEN+1 ); } /* dump out the buffer */ if( system->my_rank == MASTER_NODE ) fprintf( out_control->strj, "%s", out_control->buffer ); return SUCCESS; } int Write_Atoms( reax_system *system, control_params *control, output_controls *out_control, mpi_datatypes *mpi_data ) { int i, me, np, line_len, buffer_len, buffer_req, cnt; MPI_Status status; reax_atom *p_atom; me = system->my_rank; np = system->wsize; line_len = out_control->atom_line_len; Write_Skip_Line( out_control, mpi_data, me, system->bigN*line_len, system->bigN ); if( out_control->traj_method == REG_TRAJ && me == MASTER_NODE ) buffer_req = system->bigN * line_len + 1; else buffer_req = system->n * line_len + 1; if( buffer_req > out_control->buffer_len * DANGER_ZONE ) Reallocate_Output_Buffer( out_control, buffer_req, mpi_data->world ); /* fill in buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; for( i = 0; i < system->n; ++i ) { p_atom = &( system->my_atoms[i] ); switch( out_control->atom_info ) { case OPT_ATOM_BASIC: sprintf( out_control->line, ATOM_BASIC, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->q ); break; case OPT_ATOM_wF: sprintf( out_control->line, ATOM_wF, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->f[0], p_atom->f[1], p_atom->f[2], p_atom->q ); break; case OPT_ATOM_wV: sprintf( out_control->line, ATOM_wV, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->v[0], p_atom->v[1], p_atom->v[2], p_atom->q ); break; case OPT_ATOM_FULL: sprintf( out_control->line, ATOM_FULL, p_atom->orig_id, p_atom->x[0], p_atom->x[1], p_atom->x[2], p_atom->v[0], p_atom->v[1], p_atom->v[2], p_atom->f[0], p_atom->f[1], p_atom->f[2], p_atom->q ); break; default: fprintf( stderr, "write_traj_atoms: unknown atom trajectroy format!\n"); MPI_Abort( mpi_data->world, UNKNOWN_OPTION ); } strncpy( out_control->buffer + i*line_len, out_control->line, line_len+1 ); } if( me != MASTER_NODE ) MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np*ATOM_LINES+me, mpi_data->world ); else{ buffer_len = system->n * line_len; for( i = 0; i < np; ++i ) if( i != MASTER_NODE ) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*ATOM_LINES+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Write_Bonds(reax_system *system, control_params *control, reax_list *bonds, output_controls *out_control, mpi_datatypes *mpi_data) { int i, j, pj, me, np; int my_bonds, num_bonds; int line_len, buffer_len, buffer_req, cnt; MPI_Status status; bond_data *bo_ij; me = system->my_rank; np = system->wsize; line_len = out_control->bond_line_len; /* count the number of bonds I will write */ my_bonds = 0; for( i=0; i < system->n; ++i ) for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { j = bonds->select.bond_list[pj].nbr; if( system->my_atoms[i].orig_id <= system->my_atoms[j].orig_id && bonds->select.bond_list[pj].bo_data.BO >= control->bg_cut ) ++my_bonds; } /* allreduce - total number of bonds */ MPI_Allreduce( &my_bonds, &num_bonds, 1, MPI_INT, MPI_SUM, mpi_data->world ); Write_Skip_Line( out_control, mpi_data, me, num_bonds*line_len, num_bonds ); if( out_control->traj_method == REG_TRAJ && me == MASTER_NODE ) buffer_req = num_bonds * line_len + 1; else buffer_req = my_bonds * line_len + 1; if( buffer_req > out_control->buffer_len * DANGER_ZONE ) Reallocate_Output_Buffer( out_control, buffer_req, mpi_data->world ); /* fill in the buffer */ out_control->line[0] = 0; out_control->buffer[0] = 0; my_bonds = 0; for( i=0; i < system->n; ++i ) { for( pj = Start_Index(i, bonds); pj < End_Index(i, bonds); ++pj ) { bo_ij = &( bonds->select.bond_list[pj] ); j = bo_ij->nbr; if( system->my_atoms[i].orig_id <= system->my_atoms[j].orig_id && bo_ij->bo_data.BO >= control->bg_cut ) { switch( out_control->bond_info ) { case OPT_BOND_BASIC: sprintf( out_control->line, BOND_BASIC, system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, bo_ij->d, bo_ij->bo_data.BO ); break; case OPT_BOND_FULL: sprintf( out_control->line, BOND_FULL, system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, bo_ij->d, bo_ij->bo_data.BO, bo_ij->bo_data.BO_s, bo_ij->bo_data.BO_pi, bo_ij->bo_data.BO_pi2 ); break; default: fprintf(stderr, "write_traj_bonds: FATAL! invalid bond_info option"); MPI_Abort( mpi_data->world, UNKNOWN_OPTION ); } strncpy( out_control->buffer + my_bonds*line_len, out_control->line, line_len+1 ); ++my_bonds; } } } if( me != MASTER_NODE ) MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np*BOND_LINES+me, mpi_data->world ); else{ buffer_len = my_bonds * line_len; for( i = 0; i < np; ++i ) if( i != MASTER_NODE ) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*BOND_LINES+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Write_Angles( reax_system *system, control_params *control, reax_list *bonds, reax_list *thb_intrs, output_controls *out_control, mpi_datatypes *mpi_data ) { int i, j, k, pi, pk, me, np; int my_angles, num_angles; int line_len, buffer_len, buffer_req, cnt; bond_data *bo_ij, *bo_jk; three_body_interaction_data *angle_ijk; MPI_Status status; me = system->my_rank; np = system->wsize; line_len = out_control->angle_line_len; /* count the number of valence angles I will output */ my_angles = 0; for( j = 0; j < system->n; ++j ) for( pi = Start_Index(j, bonds); pi < End_Index(j, bonds); ++pi ) { bo_ij = &(bonds->select.bond_list[pi]); i = bo_ij->nbr; if( bo_ij->bo_data.BO >= control->bg_cut ) // physical j&i bond for( pk = Start_Index( pi, thb_intrs ); pk < End_Index( pi, thb_intrs ); ++pk ) { angle_ijk = &(thb_intrs->select.three_body_list[pk]); k = angle_ijk->thb; bo_jk = &(bonds->select.bond_list[ angle_ijk->pthb ]); if( system->my_atoms[i].orig_id < system->my_atoms[k].orig_id && bo_jk->bo_data.BO >= control->bg_cut ) // physical j&k bond ++my_angles; } } /* total number of valences */ MPI_Allreduce(&my_angles, &num_angles, 1, MPI_INT, MPI_SUM, mpi_data->world); Write_Skip_Line( out_control, mpi_data, me, num_angles*line_len, num_angles ); if( out_control->traj_method == REG_TRAJ && me == MASTER_NODE ) buffer_req = num_angles * line_len + 1; else buffer_req = my_angles * line_len + 1; if( buffer_req > out_control->buffer_len * DANGER_ZONE ) Reallocate_Output_Buffer( out_control, buffer_req, mpi_data->world ); /* fill in the buffer */ my_angles = 0; out_control->line[0] = 0; out_control->buffer[0] = 0; for( j = 0; j < system->n; ++j ) for( pi = Start_Index(j, bonds); pi < End_Index(j, bonds); ++pi ) { bo_ij = &(bonds->select.bond_list[pi]); i = bo_ij->nbr; if( bo_ij->bo_data.BO >= control->bg_cut ) // physical j&i bond for( pk = Start_Index( pi, thb_intrs ); pk < End_Index( pi, thb_intrs ); ++pk ) { angle_ijk = &(thb_intrs->select.three_body_list[pk]); k = angle_ijk->thb; bo_jk = &(bonds->select.bond_list[ angle_ijk->pthb ]); if( system->my_atoms[i].orig_id < system->my_atoms[k].orig_id && bo_jk->bo_data.BO >= control->bg_cut ) { // physical j&k bond sprintf( out_control->line, ANGLE_BASIC, system->my_atoms[i].orig_id, system->my_atoms[j].orig_id, system->my_atoms[k].orig_id, RAD2DEG( angle_ijk->theta ) ); strncpy( out_control->buffer + my_angles*line_len, out_control->line, line_len+1 ); ++my_angles; } } } if( me != MASTER_NODE ) MPI_Send( out_control->buffer, buffer_req-1, MPI_CHAR, MASTER_NODE, np*ANGLE_LINES+me, mpi_data->world ); else{ buffer_len = my_angles * line_len; for( i = 0; i < np; ++i ) if( i != MASTER_NODE ) { MPI_Recv( out_control->buffer + buffer_len, buffer_req - buffer_len, MPI_CHAR, i, np*ANGLE_LINES+i, mpi_data->world, &status ); MPI_Get_count( &status, MPI_CHAR, &cnt ); buffer_len += cnt; } out_control->buffer[buffer_len] = 0; fprintf( out_control->strj, "%s", out_control->buffer ); } return SUCCESS; } int Append_Frame( reax_system *system, control_params *control, simulation_data *data, reax_list **lists, output_controls *out_control, mpi_datatypes *mpi_data ) { Write_Frame_Header( system, control, data, out_control, mpi_data ); if( out_control->write_atoms ) Write_Atoms( system, control, out_control, mpi_data ); if( out_control->write_bonds ) Write_Bonds( system, control, (*lists + BONDS), out_control, mpi_data ); if( out_control->write_angles ) Write_Angles( system, control, (*lists + BONDS), (*lists + THREE_BODIES), out_control, mpi_data ); return SUCCESS; } int End_Traj( int my_rank, output_controls *out_control ) { if( my_rank == MASTER_NODE ) fclose( out_control->strj ); free( out_control->buffer ); free( out_control->line ); return SUCCESS; } diff --git a/src/USER-REAXC/reaxc_types.h b/src/USER-REAXC/reaxc_types.h index 816906ff3..b05e86f16 100644 --- a/src/USER-REAXC/reaxc_types.h +++ b/src/USER-REAXC/reaxc_types.h @@ -1,889 +1,854 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #ifndef __REAX_TYPES_H_ #define __REAX_TYPES_H_ #include "lmptype.h" #include "ctype.h" #include "math.h" #include "mpi.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "sys/time.h" #include "time.h" /************* SOME DEFS - crucial for reax_types.h *********/ #define LAMMPS_REAX //#define DEBUG //#define DEBUG_FOCUS //#define TEST_ENERGY //#define TEST_FORCES //#define CG_PERFORMANCE //#define LOG_PERFORMANCE //#define STANDARD_BOUNDARIES //#define OLD_BOUNDARIES //#define MIDPOINT_BOUNDARIES #define REAX_MAX_STR 1024 #define REAX_MAX_NBRS 6 #define REAX_MAX_3BODY_PARAM 5 #define REAX_MAX_4BODY_PARAM 5 #define REAX_MAX_ATOM_TYPES 25 #define REAX_MAX_MOLECULE_SIZE 20 #define MAX_BOND 20 // same as reaxc_defs.h /********************** TYPE DEFINITIONS ********************/ typedef int ivec[3]; typedef double real; typedef real rvec[3]; typedef real rtensor[3][3]; typedef real rvec2[2]; typedef real rvec4[4]; -typedef LAMMPS_NS::tagint rc_tagint; - -typedef struct { - int step, bigN; - real T, xi, v_xi, v_xi_old, G_xi; - rtensor box; -} restart_header; - -typedef struct { - rc_tagint orig_id, type; - char name[8]; - rvec x, v; -} restart_atom; - -typedef struct -{ - rc_tagint orig_id; - int imprt_id; - int type; - int num_bonds; - int num_hbonds; - char name[8]; - rvec x; // position - rvec v; // velocity - rvec f_old; // old force - rvec4 s, t; // for calculating q -} mpi_atom; - -typedef struct -{ - rc_tagint orig_id; - int imprt_id; - int type; - int num_bonds; - int num_hbonds; - rvec x; // position -} boundary_atom; +// import LAMMPS' definition of tagint +typedef LAMMPS_NS::tagint rc_tagint; typedef struct { int cnt; int *index; void *out_atoms; } mpi_out_data; typedef struct { MPI_Comm world; MPI_Comm comm_mesh3D; MPI_Datatype sys_info; MPI_Datatype mpi_atom_type; MPI_Datatype boundary_atom_type; MPI_Datatype mpi_rvec, mpi_rvec2; MPI_Datatype restart_atom_type; MPI_Datatype header_line; MPI_Datatype header_view; MPI_Datatype init_desc_line; MPI_Datatype init_desc_view; MPI_Datatype atom_line; MPI_Datatype atom_view; MPI_Datatype bond_line; MPI_Datatype bond_view; MPI_Datatype angle_line; MPI_Datatype angle_view; mpi_out_data out_buffers[REAX_MAX_NBRS]; void *in1_buffer; void *in2_buffer; } mpi_datatypes; typedef struct { int n_global; real* l; int vdw_type; } global_parameters; typedef struct { /* Line one in field file */ char name[15]; // Two character atom name real r_s; real valency; // Valency of the atom real mass; // Mass of atom real r_vdw; real epsilon; real gamma; real r_pi; real valency_e; real nlp_opt; /* Line two in field file */ real alpha; real gamma_w; real valency_boc; real p_ovun5; real chi; real eta; int p_hbond; // 1 for H, 2 for hbonding atoms (O,S,P,N), 0 for others /* Line three in field file */ real r_pi_pi; real p_lp2; real b_o_131; real b_o_132; real b_o_133; /* Line four in the field file */ real p_ovun2; real p_val3; real valency_val; real p_val5; real rcore2; real ecore2; real acore2; /* Line five in the ffield file, only for lgvdw yes */ real lgcij; real lgre; } single_body_parameters; /* Two Body Parameters */ typedef struct { /* Bond Order parameters */ real p_bo1,p_bo2,p_bo3,p_bo4,p_bo5,p_bo6; real r_s, r_p, r_pp; // r_o distances in BO formula real p_boc3, p_boc4, p_boc5; /* Bond Energy parameters */ real p_be1, p_be2; real De_s, De_p, De_pp; /* Over/Under coordination parameters */ real p_ovun1; /* Van der Waal interaction parameters */ real D; real alpha; real r_vdW; real gamma_w; real rcore, ecore, acore; real lgcij, lgre; /* electrostatic parameters */ real gamma; // note: this parameter is gamma^-3 and not gamma. real v13cor, ovc; } two_body_parameters; /* 3-body parameters */ typedef struct { /* valence angle */ real theta_00; real p_val1, p_val2, p_val4, p_val7; /* penalty */ real p_pen1; /* 3-body conjugation */ real p_coa1; } three_body_parameters; typedef struct{ int cnt; three_body_parameters prm[REAX_MAX_3BODY_PARAM]; } three_body_header; /* hydrogen-bond parameters */ typedef struct{ real r0_hb, p_hb1, p_hb2, p_hb3; } hbond_parameters; /* 4-body parameters */ typedef struct { real V1, V2, V3; /* torsion angle */ real p_tor1; /* 4-body conjugation */ real p_cot1; } four_body_parameters; typedef struct { int cnt; four_body_parameters prm[REAX_MAX_4BODY_PARAM]; } four_body_header; typedef struct { int num_atom_types; global_parameters gp; single_body_parameters *sbp; two_body_parameters **tbp; three_body_header ***thbp; hbond_parameters ***hbp; four_body_header ****fbp; } reax_interaction; struct _reax_atom { rc_tagint orig_id; int imprt_id; int type; char name[8]; rvec x; // position rvec v; // velocity rvec f; // force rvec f_old; real q; // charge rvec4 s; // they take part in rvec4 t; // computing q int Hindex; int num_bonds; int num_hbonds; int renumber; int numbonds; // true number of bonds around atoms int nbr_id[MAX_BOND]; // ids of neighbors around atoms double nbr_bo[MAX_BOND]; // BO values of bond between i and nbr double sum_bo, no_lp; // sum of BO values and no. of lone pairs }; typedef _reax_atom reax_atom; typedef struct { real V; rvec min, max, box_norms; rtensor box, box_inv; rtensor trans, trans_inv; rtensor g; } simulation_box; struct grid_cell { real cutoff; rvec min, max; ivec rel_box; int mark; int type; int str; int end; int top; int* atoms; struct grid_cell** nbrs; ivec* nbrs_x; rvec* nbrs_cp; }; typedef struct grid_cell grid_cell; typedef struct { int total, max_atoms, max_nbrs; ivec ncells; rvec cell_len; rvec inv_len; ivec bond_span; ivec nonb_span; ivec vlist_span; ivec native_cells; ivec native_str; ivec native_end; real ghost_cut; ivec ghost_span; ivec ghost_nonb_span; ivec ghost_hbond_span; ivec ghost_bond_span; grid_cell*** cells; ivec *order; } grid; typedef struct { int rank; int est_send, est_recv; int atoms_str, atoms_cnt; ivec rltv, prdc; rvec bndry_min, bndry_max; int send_type; int recv_type; ivec str_send; ivec end_send; ivec str_recv; ivec end_recv; } neighbor_proc; typedef struct { int N; int exc_gcells; int exc_atoms; } bound_estimate; typedef struct { real ghost_nonb; real ghost_hbond; real ghost_bond; real ghost_cutoff; } boundary_cutoff; using LAMMPS_NS::Pair; struct _reax_system { reax_interaction reax_param; int n, N, bigN, numH; int local_cap, total_cap, gcell_cap, Hcap; int est_recv, est_trans, max_recved; int wsize, my_rank, num_nbrs; ivec my_coords; neighbor_proc my_nbrs[REAX_MAX_NBRS]; int *global_offset; simulation_box big_box, my_box, my_ext_box; grid my_grid; boundary_cutoff bndry_cuts; reax_atom *my_atoms; class Pair *pair_ptr; int my_bonds; int mincap; real safezone, saferzone; }; typedef _reax_system reax_system; /* system control parameters */ typedef struct { char sim_name[REAX_MAX_STR]; int nprocs; ivec procs_by_dim; /* ensemble values: 0 : NVE 1 : bNVT (Berendsen) 2 : nhNVT (Nose-Hoover) 3 : sNPT (Parrinello-Rehman-Nose-Hoover) semiisotropic 4 : iNPT (Parrinello-Rehman-Nose-Hoover) isotropic 5 : NPT (Parrinello-Rehman-Nose-Hoover) Anisotropic*/ int ensemble; int nsteps; real dt; int geo_format; int restart; int restrict_bonds; int remove_CoM_vel; int random_vel; int reposition_atoms; int reneighbor; real vlist_cut; real bond_cut; real nonb_cut, nonb_low; real hbond_cut; real user_ghost_cut; real bg_cut; real bo_cut; real thb_cut; real thb_cutsq; int tabulate; int qeq_freq; real q_err; int refactor; real droptol; real T_init, T_final, T; real Tau_T; int T_mode; real T_rate, T_freq; int virial; rvec P, Tau_P, Tau_PT; int press_mode; real compressibility; int molecular_analysis; int num_ignored; int ignore[REAX_MAX_ATOM_TYPES]; int dipole_anal; int freq_dipole_anal; int diffusion_coef; int freq_diffusion_coef; int restrict_type; int lgflag; } control_params; typedef struct { real T; real xi; real v_xi; real v_xi_old; real G_xi; } thermostat; typedef struct { real P; real eps; real v_eps; real v_eps_old; real a_eps; } isotropic_barostat; typedef struct { rtensor P; real P_scalar; real eps; real v_eps; real v_eps_old; real a_eps; rtensor h0; rtensor v_g0; rtensor v_g0_old; rtensor a_g0; } flexible_barostat; typedef struct { real start; real end; real elapsed; real total; real comm; real nbrs; real init_forces; real bonded; real nonb; real qEq; int s_matvecs; int t_matvecs; } reax_timing; typedef struct { real e_tot; real e_kin; // Total kinetic energy real e_pot; real e_bond; // Total bond energy real e_ov; // Total over coordination real e_un; // Total under coordination energy real e_lp; // Total under coordination energy real e_ang; // Total valance angle energy real e_pen; // Total penalty energy real e_coa; // Total three body conjgation energy real e_hb; // Total Hydrogen bond energy real e_tor; // Total torsional energy real e_con; // Total four body conjugation energy real e_vdW; // Total van der Waals energy real e_ele; // Total electrostatics energy real e_pol; // Polarization energy } energy_data; typedef struct { int step; int prev_steps; real time; real M; // Total Mass real inv_M; // 1 / Total Mass rvec xcm; // Center of mass rvec vcm; // Center of mass velocity rvec fcm; // Center of mass force rvec amcm; // Angular momentum of CoM rvec avcm; // Angular velocity of CoM real etran_cm; // Translational kinetic energy of CoM real erot_cm; // Rotational kinetic energy of CoM rtensor kinetic; // Kinetic energy tensor rtensor virial; // Hydrodynamic virial energy_data my_en; energy_data sys_en; real N_f; //Number of degrees of freedom rvec t_scale; rtensor p_scale; thermostat therm; // Used in Nose_Hoover method isotropic_barostat iso_bar; flexible_barostat flex_bar; real inv_W; real kin_press; rvec int_press; rvec my_ext_press; rvec ext_press; rvec tot_press; reax_timing timing; } simulation_data; typedef struct{ int thb; int pthb; // pointer to the third body on the central atom's nbrlist real theta, cos_theta; rvec dcos_di, dcos_dj, dcos_dk; } three_body_interaction_data; typedef struct { int nbr; ivec rel_box; real d; rvec dvec; } far_neighbor_data; typedef struct { int nbr; int scl; far_neighbor_data *ptr; } hbond_data; typedef struct{ int wrt; rvec dVal; } dDelta_data; typedef struct{ int wrt; rvec dBO, dBOpi, dBOpi2; } dbond_data; typedef struct{ real BO, BO_s, BO_pi, BO_pi2; real Cdbo, Cdbopi, Cdbopi2; real C1dbo, C2dbo, C3dbo; real C1dbopi, C2dbopi, C3dbopi, C4dbopi; real C1dbopi2, C2dbopi2, C3dbopi2, C4dbopi2; rvec dBOp, dln_BOp_s, dln_BOp_pi, dln_BOp_pi2; } bond_order_data; typedef struct { int nbr; int sym_index; int dbond_index; ivec rel_box; // rvec ext_factor; real d; rvec dvec; bond_order_data bo_data; } bond_data; typedef struct { int j; real val; } sparse_matrix_entry; typedef struct { int cap, n, m; int *start, *end; sparse_matrix_entry *entries; } sparse_matrix; typedef struct { int num_far; int H, Htop; int hbonds, num_hbonds; int bonds, num_bonds; int num_3body; int gcell_atoms; } reallocate_data; typedef struct { int allocated; /* communication storage */ real *tmp_dbl[REAX_MAX_NBRS]; rvec *tmp_rvec[REAX_MAX_NBRS]; rvec2 *tmp_rvec2[REAX_MAX_NBRS]; int *within_bond_box; /* bond order related storage */ real *total_bond_order; real *Deltap, *Deltap_boc; real *Delta, *Delta_lp, *Delta_lp_temp, *Delta_e, *Delta_boc, *Delta_val; real *dDelta_lp, *dDelta_lp_temp; real *nlp, *nlp_temp, *Clp, *vlpex; rvec *dDeltap_self; int *bond_mark, *done_after; /* QEq storage */ sparse_matrix *H, *L, *U; real *Hdia_inv, *b_s, *b_t, *b_prc, *b_prm, *s, *t; real *droptol; rvec2 *b, *x; /* GMRES storage */ real *y, *z, *g; real *hc, *hs; real **h, **v; /* CG storage */ real *r, *d, *q, *p; rvec2 *r2, *d2, *q2, *p2; /* Taper */ real Tap[8]; //Tap7, Tap6, Tap5, Tap4, Tap3, Tap2, Tap1, Tap0; /* storage for analysis */ int *mark, *old_mark; rvec *x_old; /* storage space for bond restrictions */ int *restricted; int **restricted_list; /* integrator */ rvec *v_const; /* force calculations */ real *CdDelta; // coefficient of dDelta rvec *f; reallocate_data realloc; } storage; typedef union { void *v; three_body_interaction_data *three_body_list; bond_data *bond_list; dbond_data *dbo_list; dDelta_data *dDelta_list; far_neighbor_data *far_nbr_list; hbond_data *hbond_list; } list_type; struct _reax_list { int allocated; int n; int num_intrs; int *index; int *end_index; int type; list_type select; }; typedef _reax_list reax_list; typedef struct { FILE *strj; int trj_offset; int atom_line_len; int bond_line_len; int angle_line_len; int write_atoms; int write_bonds; int write_angles; char *line; int buffer_len; char *buffer; FILE *out; FILE *pot; FILE *log; FILE *mol, *ign; FILE *dpl; FILE *drft; FILE *pdb; FILE *prs; int write_steps; int traj_compress; int traj_method; char traj_title[81]; int atom_info; int bond_info; int angle_info; int restart_format; int restart_freq; int debug_level; int energy_update_freq; } output_controls; typedef struct { int atom_count; int atom_list[REAX_MAX_MOLECULE_SIZE]; int mtypes[REAX_MAX_ATOM_TYPES]; } molecule; typedef struct { real H; real e_vdW, CEvd; real e_ele, CEclmb; } LR_data; typedef struct { real a, b, c, d; } cubic_spline_coef; typedef struct { real xmin, xmax; int n; real dx, inv_dx; real a; real m; real c; LR_data *y; cubic_spline_coef *H; cubic_spline_coef *vdW, *CEvd; cubic_spline_coef *ele, *CEclmb; } LR_lookup_table; extern LR_lookup_table **LR; /* function pointer defs */ typedef void (*evolve_function)(reax_system*, control_params*, simulation_data*, storage*, reax_list**, output_controls*, mpi_datatypes* ); typedef void (*interaction_function) (reax_system*, control_params*, simulation_data*, storage*, reax_list**, output_controls*); typedef void (*print_interaction)(reax_system*, control_params*, simulation_data*, storage*, reax_list**, output_controls*); typedef real (*lookup_function)(real); typedef void (*message_sorter) (reax_system*, int, int, int, mpi_out_data*); typedef void (*unpacker) ( reax_system*, int, void*, int, neighbor_proc*, int ); typedef void (*dist_packer) (void*, mpi_out_data*); typedef void (*coll_unpacker) (void*, void*, mpi_out_data*); #endif diff --git a/src/USER-REAXC/reaxc_valence_angles.cpp b/src/USER-REAXC/reaxc_valence_angles.cpp index 532d9a6a7..60f985598 100644 --- a/src/USER-REAXC/reaxc_valence_angles.cpp +++ b/src/USER-REAXC/reaxc_valence_angles.cpp @@ -1,409 +1,416 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_valence_angles.h" #include "reaxc_bond_orders.h" #include "reaxc_list.h" #include "reaxc_vector.h" +static real Dot( real* v1, real* v2, int k ) +{ + real ret = 0.0; + + for( int i=0; i < k; ++i ) + ret += v1[i] * v2[i]; + + return ret; +} + void Calculate_Theta( rvec dvec_ji, real d_ji, rvec dvec_jk, real d_jk, real *theta, real *cos_theta ) { (*cos_theta) = Dot( dvec_ji, dvec_jk, 3 ) / ( d_ji * d_jk ); if( *cos_theta > 1. ) *cos_theta = 1.0; if( *cos_theta < -1. ) *cos_theta = -1.0; (*theta) = acos( *cos_theta ); } void Calculate_dCos_Theta( rvec dvec_ji, real d_ji, rvec dvec_jk, real d_jk, rvec* dcos_theta_di, rvec* dcos_theta_dj, rvec* dcos_theta_dk ) { int t; real sqr_d_ji = SQR(d_ji); real sqr_d_jk = SQR(d_jk); real inv_dists = 1.0 / (d_ji * d_jk); real inv_dists3 = pow( inv_dists, 3.0 ); real dot_dvecs = Dot( dvec_ji, dvec_jk, 3 ); real Cdot_inv3 = dot_dvecs * inv_dists3; for( t = 0; t < 3; ++t ) { (*dcos_theta_di)[t] = dvec_jk[t] * inv_dists - Cdot_inv3 * sqr_d_jk * dvec_ji[t]; (*dcos_theta_dj)[t] = -(dvec_jk[t] + dvec_ji[t]) * inv_dists + Cdot_inv3 * ( sqr_d_jk * dvec_ji[t] + sqr_d_ji * dvec_jk[t] ); (*dcos_theta_dk)[t] = dvec_ji[t] * inv_dists - Cdot_inv3 * sqr_d_ji * dvec_jk[t]; } } void Valence_Angles( reax_system *system, control_params *control, simulation_data *data, storage *workspace, reax_list **lists, output_controls *out_control ) { int i, j, pi, k, pk, t; int type_i, type_j, type_k; int start_j, end_j, start_pk, end_pk; int cnt, num_thb_intrs; real temp, temp_bo_jt, pBOjt7; real p_val1, p_val2, p_val3, p_val4, p_val5; real p_val6, p_val7, p_val8, p_val9, p_val10; real p_pen1, p_pen2, p_pen3, p_pen4; real p_coa1, p_coa2, p_coa3, p_coa4; real trm8, expval6, expval7, expval2theta, expval12theta, exp3ij, exp3jk; real exp_pen2ij, exp_pen2jk, exp_pen3, exp_pen4, trm_pen34, exp_coa2; real dSBO1, dSBO2, SBO, SBO2, CSBO2, SBOp, prod_SBO, vlpadj; real CEval1, CEval2, CEval3, CEval4, CEval5, CEval6, CEval7, CEval8; real CEpen1, CEpen2, CEpen3; real e_ang, e_coa, e_pen; real CEcoa1, CEcoa2, CEcoa3, CEcoa4, CEcoa5; real Cf7ij, Cf7jk, Cf8j, Cf9j; real f7_ij, f7_jk, f8_Dj, f9_Dj; real Ctheta_0, theta_0, theta_00, theta, cos_theta, sin_theta; - real r_ij, r_jk; real BOA_ij, BOA_jk; rvec force, ext_press; // Tallying variables - real eng_tmp, f_scaler, fi_tmp[3], fj_tmp[3], fk_tmp[3]; + real eng_tmp, fi_tmp[3], fj_tmp[3], fk_tmp[3]; real delij[3], delkj[3]; three_body_header *thbh; three_body_parameters *thbp; three_body_interaction_data *p_ijk, *p_kji; bond_data *pbond_ij, *pbond_jk, *pbond_jt; bond_order_data *bo_ij, *bo_jk, *bo_jt; reax_list *bonds = (*lists) + BONDS; reax_list *thb_intrs = (*lists) + THREE_BODIES; /* global parameters used in these calculations */ p_val6 = system->reax_param.gp.l[14]; p_val8 = system->reax_param.gp.l[33]; p_val9 = system->reax_param.gp.l[16]; p_val10 = system->reax_param.gp.l[17]; num_thb_intrs = 0; for( j = 0; j < system->N; ++j ) { // Ray: the first one with system->N type_j = system->my_atoms[j].type; if (type_j < 0) continue; start_j = Start_Index(j, bonds); end_j = End_Index(j, bonds); p_val3 = system->reax_param.sbp[ type_j ].p_val3; p_val5 = system->reax_param.sbp[ type_j ].p_val5; SBOp = 0, prod_SBO = 1; for( t = start_j; t < end_j; ++t ) { bo_jt = &(bonds->select.bond_list[t].bo_data); SBOp += (bo_jt->BO_pi + bo_jt->BO_pi2); temp = SQR( bo_jt->BO ); temp *= temp; temp *= temp; prod_SBO *= exp( -temp ); } if( workspace->vlpex[j] >= 0 ){ vlpadj = 0; dSBO2 = prod_SBO - 1; } else{ vlpadj = workspace->nlp[j]; dSBO2 = (prod_SBO - 1) * (1 - p_val8 * workspace->dDelta_lp[j]); } SBO = SBOp + (1 - prod_SBO) * (-workspace->Delta_boc[j] - p_val8 * vlpadj); dSBO1 = -8 * prod_SBO * ( workspace->Delta_boc[j] + p_val8 * vlpadj ); if( SBO <= 0 ) SBO2 = 0, CSBO2 = 0; else if( SBO > 0 && SBO <= 1 ) { SBO2 = pow( SBO, p_val9 ); CSBO2 = p_val9 * pow( SBO, p_val9 - 1 ); } else if( SBO > 1 && SBO < 2 ) { SBO2 = 2 - pow( 2-SBO, p_val9 ); CSBO2 = p_val9 * pow( 2 - SBO, p_val9 - 1 ); } else SBO2 = 2, CSBO2 = 0; expval6 = exp( p_val6 * workspace->Delta_boc[j] ); for( pi = start_j; pi < end_j; ++pi ) { Set_Start_Index( pi, num_thb_intrs, thb_intrs ); pbond_ij = &(bonds->select.bond_list[pi]); bo_ij = &(pbond_ij->bo_data); BOA_ij = bo_ij->BO - control->thb_cut; if( BOA_ij/*bo_ij->BO*/ > 0.0 && ( j < system->n || pbond_ij->nbr < system->n ) ) { i = pbond_ij->nbr; - r_ij = pbond_ij->d; type_i = system->my_atoms[i].type; for( pk = start_j; pk < pi; ++pk ) { start_pk = Start_Index( pk, thb_intrs ); end_pk = End_Index( pk, thb_intrs ); for( t = start_pk; t < end_pk; ++t ) if( thb_intrs->select.three_body_list[t].thb == i ) { p_ijk = &(thb_intrs->select.three_body_list[num_thb_intrs] ); p_kji = &(thb_intrs->select.three_body_list[t]); p_ijk->thb = bonds->select.bond_list[pk].nbr; p_ijk->pthb = pk; p_ijk->theta = p_kji->theta; rvec_Copy( p_ijk->dcos_di, p_kji->dcos_dk ); rvec_Copy( p_ijk->dcos_dj, p_kji->dcos_dj ); rvec_Copy( p_ijk->dcos_dk, p_kji->dcos_di ); ++num_thb_intrs; break; } } for( pk = pi+1; pk < end_j; ++pk ) { pbond_jk = &(bonds->select.bond_list[pk]); bo_jk = &(pbond_jk->bo_data); BOA_jk = bo_jk->BO - control->thb_cut; k = pbond_jk->nbr; type_k = system->my_atoms[k].type; p_ijk = &( thb_intrs->select.three_body_list[num_thb_intrs] ); Calculate_Theta( pbond_ij->dvec, pbond_ij->d, pbond_jk->dvec, pbond_jk->d, &theta, &cos_theta ); Calculate_dCos_Theta( pbond_ij->dvec, pbond_ij->d, pbond_jk->dvec, pbond_jk->d, &(p_ijk->dcos_di), &(p_ijk->dcos_dj), &(p_ijk->dcos_dk) ); p_ijk->thb = k; p_ijk->pthb = pk; p_ijk->theta = theta; sin_theta = sin( theta ); if( sin_theta < 1.0e-5 ) sin_theta = 1.0e-5; ++num_thb_intrs; if( (j < system->n) && (BOA_jk > 0.0) && (bo_ij->BO > control->thb_cut) && (bo_jk->BO > control->thb_cut) && (bo_ij->BO * bo_jk->BO > control->thb_cutsq) ) { - r_jk = pbond_jk->d; thbh = &( system->reax_param.thbp[ type_i ][ type_j ][ type_k ] ); for( cnt = 0; cnt < thbh->cnt; ++cnt ) { if( fabs(thbh->prm[cnt].p_val1) > 0.001 ) { thbp = &( thbh->prm[cnt] ); /* ANGLE ENERGY */ p_val1 = thbp->p_val1; p_val2 = thbp->p_val2; p_val4 = thbp->p_val4; p_val7 = thbp->p_val7; theta_00 = thbp->theta_00; exp3ij = exp( -p_val3 * pow( BOA_ij, p_val4 ) ); f7_ij = 1.0 - exp3ij; Cf7ij = p_val3 * p_val4 * pow( BOA_ij, p_val4 - 1.0 ) * exp3ij; exp3jk = exp( -p_val3 * pow( BOA_jk, p_val4 ) ); f7_jk = 1.0 - exp3jk; Cf7jk = p_val3 * p_val4 * pow( BOA_jk, p_val4 - 1.0 ) * exp3jk; expval7 = exp( -p_val7 * workspace->Delta_boc[j] ); trm8 = 1.0 + expval6 + expval7; f8_Dj = p_val5 - ( (p_val5 - 1.0) * (2.0 + expval6) / trm8 ); Cf8j = ( (1.0 - p_val5) / SQR(trm8) ) * ( p_val6 * expval6 * trm8 - (2.0 + expval6) * ( p_val6*expval6 - p_val7*expval7 ) ); theta_0 = 180.0 - theta_00 * (1.0 - exp(-p_val10 * (2.0 - SBO2))); theta_0 = DEG2RAD( theta_0 ); expval2theta = exp( -p_val2 * SQR(theta_0 - theta) ); if( p_val1 >= 0 ) expval12theta = p_val1 * (1.0 - expval2theta); else // To avoid linear Me-H-Me angles (6/6/06) expval12theta = p_val1 * -expval2theta; CEval1 = Cf7ij * f7_jk * f8_Dj * expval12theta; CEval2 = Cf7jk * f7_ij * f8_Dj * expval12theta; CEval3 = Cf8j * f7_ij * f7_jk * expval12theta; CEval4 = -2.0 * p_val1 * p_val2 * f7_ij * f7_jk * f8_Dj * expval2theta * (theta_0 - theta); Ctheta_0 = p_val10 * DEG2RAD(theta_00) * exp( -p_val10 * (2.0 - SBO2) ); CEval5 = -CEval4 * Ctheta_0 * CSBO2; CEval6 = CEval5 * dSBO1; CEval7 = CEval5 * dSBO2; CEval8 = -CEval4 / sin_theta; data->my_en.e_ang += e_ang = f7_ij * f7_jk * f8_Dj * expval12theta; /* END ANGLE ENERGY*/ /* PENALTY ENERGY */ p_pen1 = thbp->p_pen1; p_pen2 = system->reax_param.gp.l[19]; p_pen3 = system->reax_param.gp.l[20]; p_pen4 = system->reax_param.gp.l[21]; exp_pen2ij = exp( -p_pen2 * SQR( BOA_ij - 2.0 ) ); exp_pen2jk = exp( -p_pen2 * SQR( BOA_jk - 2.0 ) ); exp_pen3 = exp( -p_pen3 * workspace->Delta[j] ); exp_pen4 = exp( p_pen4 * workspace->Delta[j] ); trm_pen34 = 1.0 + exp_pen3 + exp_pen4; f9_Dj = ( 2.0 + exp_pen3 ) / trm_pen34; Cf9j = ( -p_pen3 * exp_pen3 * trm_pen34 - (2.0 + exp_pen3) * ( -p_pen3 * exp_pen3 + p_pen4 * exp_pen4 ) ) / SQR( trm_pen34 ); data->my_en.e_pen += e_pen = p_pen1 * f9_Dj * exp_pen2ij * exp_pen2jk; CEpen1 = e_pen * Cf9j / f9_Dj; temp = -2.0 * p_pen2 * e_pen; CEpen2 = temp * (BOA_ij - 2.0); CEpen3 = temp * (BOA_jk - 2.0); /* END PENALTY ENERGY */ /* COALITION ENERGY */ p_coa1 = thbp->p_coa1; p_coa2 = system->reax_param.gp.l[2]; p_coa3 = system->reax_param.gp.l[38]; p_coa4 = system->reax_param.gp.l[30]; exp_coa2 = exp( p_coa2 * workspace->Delta_val[j] ); data->my_en.e_coa += e_coa = p_coa1 / (1. + exp_coa2) * exp( -p_coa3 * SQR(workspace->total_bond_order[i]-BOA_ij) ) * exp( -p_coa3 * SQR(workspace->total_bond_order[k]-BOA_jk) ) * exp( -p_coa4 * SQR(BOA_ij - 1.5) ) * exp( -p_coa4 * SQR(BOA_jk - 1.5) ); CEcoa1 = -2 * p_coa4 * (BOA_ij - 1.5) * e_coa; CEcoa2 = -2 * p_coa4 * (BOA_jk - 1.5) * e_coa; CEcoa3 = -p_coa2 * exp_coa2 * e_coa / (1 + exp_coa2); CEcoa4 = -2 * p_coa3 * (workspace->total_bond_order[i]-BOA_ij) * e_coa; CEcoa5 = -2 * p_coa3 * (workspace->total_bond_order[k]-BOA_jk) * e_coa; /* END COALITION ENERGY */ /* FORCES */ bo_ij->Cdbo += (CEval1 + CEpen2 + (CEcoa1 - CEcoa4)); bo_jk->Cdbo += (CEval2 + CEpen3 + (CEcoa2 - CEcoa5)); workspace->CdDelta[j] += ((CEval3 + CEval7) + CEpen1 + CEcoa3); workspace->CdDelta[i] += CEcoa4; workspace->CdDelta[k] += CEcoa5; for( t = start_j; t < end_j; ++t ) { pbond_jt = &( bonds->select.bond_list[t] ); bo_jt = &(pbond_jt->bo_data); temp_bo_jt = bo_jt->BO; temp = CUBE( temp_bo_jt ); pBOjt7 = temp * temp * temp_bo_jt; bo_jt->Cdbo += (CEval6 * pBOjt7); bo_jt->Cdbopi += CEval5; bo_jt->Cdbopi2 += CEval5; } if( control->virial == 0 ) { rvec_ScaledAdd( workspace->f[i], CEval8, p_ijk->dcos_di ); rvec_ScaledAdd( workspace->f[j], CEval8, p_ijk->dcos_dj ); rvec_ScaledAdd( workspace->f[k], CEval8, p_ijk->dcos_dk ); } else { rvec_Scale( force, CEval8, p_ijk->dcos_di ); rvec_Add( workspace->f[i], force ); rvec_iMultiply( ext_press, pbond_ij->rel_box, force ); rvec_Add( data->my_ext_press, ext_press ); rvec_ScaledAdd( workspace->f[j], CEval8, p_ijk->dcos_dj ); rvec_Scale( force, CEval8, p_ijk->dcos_dk ); rvec_Add( workspace->f[k], force ); rvec_iMultiply( ext_press, pbond_jk->rel_box, force ); rvec_Add( data->my_ext_press, ext_press ); } /* tally into per-atom virials */ if( system->pair_ptr->vflag_atom || system->pair_ptr->evflag) { /* Acquire vectors */ rvec_ScaledSum( delij, 1., system->my_atoms[i].x, -1., system->my_atoms[j].x ); rvec_ScaledSum( delkj, 1., system->my_atoms[k].x, -1., system->my_atoms[j].x ); rvec_Scale( fi_tmp, -CEval8, p_ijk->dcos_di ); rvec_Scale( fj_tmp, -CEval8, p_ijk->dcos_dj ); rvec_Scale( fk_tmp, -CEval8, p_ijk->dcos_dk ); eng_tmp = e_ang + e_pen + e_coa; if( system->pair_ptr->evflag) system->pair_ptr->ev_tally(j,j,system->N,1,eng_tmp,0.0,0.0,0.0,0.0,0.0); if( system->pair_ptr->vflag_atom) system->pair_ptr->v_tally3(i,j,k,fi_tmp,fk_tmp,delij,delkj); } } } } } } Set_End_Index(pi, num_thb_intrs, thb_intrs ); } } if( num_thb_intrs >= thb_intrs->num_intrs * DANGER_ZONE ) { workspace->realloc.num_3body = num_thb_intrs; if( num_thb_intrs > thb_intrs->num_intrs ) { fprintf( stderr, "step%d-ran out of space on angle_list: top=%d, max=%d", data->step, num_thb_intrs, thb_intrs->num_intrs ); MPI_Abort( MPI_COMM_WORLD, INSUFFICIENT_MEMORY ); } } } diff --git a/src/USER-REAXC/reaxc_vector.cpp b/src/USER-REAXC/reaxc_vector.cpp index 4d5644217..256506421 100644 --- a/src/USER-REAXC/reaxc_vector.cpp +++ b/src/USER-REAXC/reaxc_vector.cpp @@ -1,500 +1,235 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #include "pair_reax_c.h" #include "reaxc_vector.h" -int Vector_isZero( real* v, int k ) -{ - for( --k; k>=0; --k ) - if( fabs( v[k] ) > ALMOST_ZERO ) - return 0; - - return 1; -} - - -void Vector_MakeZero( real *v, int k ) -{ - for( --k; k>=0; --k ) - v[k] = 0; -} - - -void Vector_Copy( real* dest, real* v, int k ) -{ - for( --k; k>=0; --k ) - dest[k] = v[k]; -} - - -void Vector_Scale( real* dest, real c, real* v, int k ) -{ - for( --k; k>=0; --k ) - dest[k] = c * v[k]; -} - - -void Vector_Sum( real* dest, real c, real* v, real d, real* y, int k ) -{ - for( --k; k>=0; --k ) - dest[k] = c * v[k] + d * y[k]; -} - - -void Vector_Add( real* dest, real c, real* v, int k ) -{ - for( --k; k>=0; --k ) - dest[k] += c * v[k]; -} - - -real Dot( real* v1, real* v2, int k ) -{ - real ret = 0; - - for( --k; k>=0; --k ) - ret += v1[k] * v2[k]; - - return ret; -} - - -real Norm( real* v1, int k ) -{ - real ret = 0; - - for( --k; k>=0; --k ) - ret += SQR( v1[k] ); - - return sqrt( ret ); -} - - -void Vector_Print( FILE *fout, char *vname, real *v, int k ) -{ - int i; - - fprintf( fout, "%s:", vname ); - for( i = 0; i < k; ++i ) - fprintf( fout, "%24.15e\n", v[i] ); - fprintf( fout, "\n" ); -} - void rvec_Copy( rvec dest, rvec src ) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2]; } + void rvec_Scale( rvec ret, real c, rvec v ) { ret[0] = c * v[0], ret[1] = c * v[1], ret[2] = c * v[2]; } void rvec_Add( rvec ret, rvec v ) { ret[0] += v[0], ret[1] += v[1], ret[2] += v[2]; } void rvec_ScaledAdd( rvec ret, real c, rvec v ) { ret[0] += c * v[0], ret[1] += c * v[1], ret[2] += c * v[2]; } void rvec_Sum( rvec ret, rvec v1 ,rvec v2 ) { ret[0] = v1[0] + v2[0]; ret[1] = v1[1] + v2[1]; ret[2] = v1[2] + v2[2]; } void rvec_ScaledSum( rvec ret, real c1, rvec v1 ,real c2, rvec v2 ) { ret[0] = c1 * v1[0] + c2 * v2[0]; ret[1] = c1 * v1[1] + c2 * v2[1]; ret[2] = c1 * v1[2] + c2 * v2[2]; } real rvec_Dot( rvec v1, rvec v2 ) { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } real rvec_ScaledDot( real c1, rvec v1, real c2, rvec v2 ) { return (c1*c2) * (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]); } void rvec_Multiply( rvec r, rvec v1, rvec v2 ) { r[0] = v1[0] * v2[0]; r[1] = v1[1] * v2[1]; r[2] = v1[2] * v2[2]; } void rvec_iMultiply( rvec r, ivec v1, rvec v2 ) { r[0] = v1[0] * v2[0]; r[1] = v1[1] * v2[1]; r[2] = v1[2] * v2[2]; } void rvec_Divide( rvec r, rvec v1, rvec v2 ) { r[0] = v1[0] / v2[0]; r[1] = v1[1] / v2[1]; r[2] = v1[2] / v2[2]; } void rvec_iDivide( rvec r, rvec v1, ivec v2 ) { r[0] = v1[0] / v2[0]; r[1] = v1[1] / v2[1]; r[2] = v1[2] / v2[2]; } void rvec_Invert( rvec r, rvec v ) { r[0] = 1. / v[0]; r[1] = 1. / v[1]; r[2] = 1. / v[2]; } void rvec_Cross( rvec ret, rvec v1, rvec v2 ) { ret[0] = v1[1] * v2[2] - v1[2] * v2[1]; ret[1] = v1[2] * v2[0] - v1[0] * v2[2]; ret[2] = v1[0] * v2[1] - v1[1] * v2[0]; } void rvec_OuterProduct( rtensor r, rvec v1, rvec v2 ) { int i, j; for( i = 0; i < 3; ++i ) for( j = 0; j < 3; ++j ) r[i][j] = v1[i] * v2[j]; } real rvec_Norm_Sqr( rvec v ) { return SQR(v[0]) + SQR(v[1]) + SQR(v[2]); } real rvec_Norm( rvec v ) { return sqrt( SQR(v[0]) + SQR(v[1]) + SQR(v[2]) ); } int rvec_isZero( rvec v ) { if( fabs(v[0]) > ALMOST_ZERO || fabs(v[1]) > ALMOST_ZERO || fabs(v[2]) > ALMOST_ZERO ) return 0; return 1; } void rvec_MakeZero( rvec v ) { v[0] = v[1] = v[2] = 0.000000000000000e+00; } -void rtensor_Multiply( rtensor ret, rtensor m1, rtensor m2 ) -{ - int i, j, k; - rtensor temp; - - if( ret == m1 || ret == m2 ) - { - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - { - temp[i][j] = 0; - for( k = 0; k < 3; ++k ) - temp[i][j] += m1[i][k] * m2[k][j]; - } - - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - ret[i][j] = temp[i][j]; - } - else - { - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - { - ret[i][j] = 0; - for( k = 0; k < 3; ++k ) - ret[i][j] += m1[i][k] * m2[k][j]; - } - } -} - void rtensor_MatVec( rvec ret, rtensor m, rvec v ) { int i; rvec temp; if( ret == v ) { for( i = 0; i < 3; ++i ) temp[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][2] * v[2]; for( i = 0; i < 3; ++i ) ret[i] = temp[i]; } else { for( i = 0; i < 3; ++i ) ret[i] = m[i][0] * v[0] + m[i][1] * v[1] + m[i][2] * v[2]; } } void rtensor_Scale( rtensor ret, real c, rtensor m ) { int i, j; for( i = 0; i < 3; ++i ) for( j = 0; j < 3; ++j ) ret[i][j] = c * m[i][j]; } -void rtensor_Add( rtensor ret, rtensor t ) -{ - int i, j; - - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - ret[i][j] += t[i][j]; -} - - -void rtensor_ScaledAdd( rtensor ret, real c, rtensor t ) -{ - int i, j; - - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - ret[i][j] += c * t[i][j]; -} - - -void rtensor_Sum( rtensor ret, rtensor t1, rtensor t2 ) -{ - int i, j; - - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - ret[i][j] = t1[i][j] + t2[i][j]; -} - - -void rtensor_ScaledSum( rtensor ret, real c1, rtensor t1, - real c2, rtensor t2 ) -{ - int i, j; - - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - ret[i][j] = c1 * t1[i][j] + c2 * t2[i][j]; -} - - -void rtensor_Copy( rtensor ret, rtensor t ) -{ - int i, j; - - for( i = 0; i < 3; ++i ) - for( j = 0; j < 3; ++j ) - ret[i][j] = t[i][j]; -} - - -void rtensor_Identity( rtensor t ) -{ - t[0][0] = t[1][1] = t[2][2] = 1; - t[0][1] = t[0][2] = t[1][0] = t[1][2] = t[2][0] = t[2][1] = 0; -} - - void rtensor_MakeZero( rtensor t ) { t[0][0] = t[0][1] = t[0][2] = 0; t[1][0] = t[1][1] = t[1][2] = 0; t[2][0] = t[2][1] = t[2][2] = 0; } -void rtensor_Transpose( rtensor ret, rtensor t ) -{ - ret[0][0] = t[0][0], ret[1][1] = t[1][1], ret[2][2] = t[2][2]; - ret[0][1] = t[1][0], ret[0][2] = t[2][0]; - ret[1][0] = t[0][1], ret[1][2] = t[2][1]; - ret[2][0] = t[0][2], ret[2][1] = t[1][2]; -} - - -real rtensor_Det( rtensor t ) -{ - return ( t[0][0] * (t[1][1] * t[2][2] - t[1][2] * t[2][1] ) + - t[0][1] * (t[1][2] * t[2][0] - t[1][0] * t[2][2] ) + - t[0][2] * (t[1][0] * t[2][1] - t[1][1] * t[2][0] ) ); -} - - -real rtensor_Trace( rtensor t ) -{ - return (t[0][0] + t[1][1] + t[2][2]); -} - - -void Print_rTensor(FILE* fp, rtensor t) -{ - int i, j; - - for (i=0; i < 3; i++) - { - fprintf(fp,"["); - for (j=0; j < 3; j++) - fprintf(fp,"%8.3f,\t",t[i][j]); - fprintf(fp,"]\n"); - } -} - - void ivec_MakeZero( ivec v ) { v[0] = v[1] = v[2] = 0; } void ivec_Copy( ivec dest, ivec src ) { dest[0] = src[0], dest[1] = src[1], dest[2] = src[2]; } void ivec_Scale( ivec dest, real C, ivec src ) { dest[0] = (int)(C * src[0]); dest[1] = (int)(C * src[1]); dest[2] = (int)(C * src[2]); } -void ivec_rScale( ivec dest, real C, rvec src ) -{ - dest[0] = (int)(C * src[0]); - dest[1] = (int)(C * src[1]); - dest[2] = (int)(C * src[2]); -} - - -int ivec_isZero( ivec v ) -{ - if( v[0]==0 && v[1]==0 && v[2]==0 ) - return 1; - return 0; -} - - -int ivec_isEqual( ivec v1, ivec v2 ) -{ - if( v1[0]==v2[0] && v1[1]==v2[1] && v1[2]==v2[2] ) - return 1; - return 0; -} - - void ivec_Sum( ivec dest, ivec v1, ivec v2 ) { dest[0] = v1[0] + v2[0]; dest[1] = v1[1] + v2[1]; dest[2] = v1[2] + v2[2]; } -void ivec_ScaledSum( ivec dest, int k1, ivec v1, int k2, ivec v2 ) -{ - dest[0] = k1*v1[0] + k2*v2[0]; - dest[1] = k1*v1[1] + k2*v2[1]; - dest[2] = k1*v1[2] + k2*v2[2]; -} - - -void ivec_Add( ivec dest, ivec v ) -{ - dest[0] += v[0]; - dest[1] += v[1]; - dest[2] += v[2]; -} - - -void ivec_ScaledAdd( ivec dest, int k, ivec v ) -{ - dest[0] += k * v[0]; - dest[1] += k * v[1]; - dest[2] += k * v[2]; -} - - - -void ivec_Max( ivec res, ivec v1, ivec v2 ) -{ - res[0] = MAX( v1[0], v2[0] ); - res[1] = MAX( v1[1], v2[1] ); - res[2] = MAX( v1[2], v2[2] ); -} - - -void ivec_Max3( ivec res, ivec v1, ivec v2, ivec v3 ) -{ - res[0] = MAX3( v1[0], v2[0], v3[0] ); - res[1] = MAX3( v1[1], v2[1], v3[1] ); - res[2] = MAX3( v1[2], v2[2], v3[2] ); -} diff --git a/src/USER-REAXC/reaxc_vector.h b/src/USER-REAXC/reaxc_vector.h index a33e249bc..189b866dc 100644 --- a/src/USER-REAXC/reaxc_vector.h +++ b/src/USER-REAXC/reaxc_vector.h @@ -1,95 +1,64 @@ /*---------------------------------------------------------------------- PuReMD - Purdue ReaxFF Molecular Dynamics Program Copyright (2010) Purdue University Hasan Metin Aktulga, hmaktulga@lbl.gov Joseph Fogarty, jcfogart@mail.usf.edu Sagar Pandit, pandit@usf.edu Ananth Y Grama, ayg@cs.purdue.edu Please cite the related publication: H. M. Aktulga, J. C. Fogarty, S. A. Pandit, A. Y. Grama, "Parallel Reactive Molecular Dynamics: Numerical Methods and Algorithmic Techniques", Parallel Computing, in press. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details: <http://www.gnu.org/licenses/>. ----------------------------------------------------------------------*/ #ifndef __VECTOR_H_ #define __VECTOR_H_ #include "pair.h" #include "reaxc_types.h" #include "reaxc_defs.h" -int Vector_isZero( real*, int ); -void Vector_MakeZero( real*, int ); -void Vector_Copy( real*, real*, int ); -void Vector_Scale( real*, real, real*, int ); -void Vector_Sum( real*, real, real*, real, real*, int ); -void Vector_Add( real*, real, real*, int ); -real Dot( real*, real*, int ); -real Norm( real*, int ); -void Vector_Print( FILE*, char*, real*, int ); - void rvec_Copy( rvec, rvec ); void rvec_Scale( rvec, real, rvec ); void rvec_Add( rvec, rvec ); void rvec_ScaledAdd( rvec, real, rvec ); void rvec_Sum( rvec, rvec, rvec ); void rvec_ScaledSum( rvec, real, rvec, real, rvec ); real rvec_Dot( rvec, rvec ); real rvec_ScaledDot( real, rvec, real, rvec ); void rvec_Multiply( rvec, rvec, rvec ); void rvec_iMultiply( rvec, ivec, rvec ); void rvec_Divide( rvec, rvec, rvec ); void rvec_iDivide( rvec, rvec, ivec ); void rvec_Invert( rvec, rvec ); void rvec_Cross( rvec, rvec, rvec ); void rvec_OuterProduct( rtensor, rvec, rvec ); real rvec_Norm_Sqr( rvec ); real rvec_Norm( rvec ); int rvec_isZero( rvec ); void rvec_MakeZero( rvec ); void rvec_Random( rvec ); void rtensor_MakeZero( rtensor ); -void rtensor_Multiply( rtensor, rtensor, rtensor ); void rtensor_MatVec( rvec, rtensor, rvec ); void rtensor_Scale( rtensor, real, rtensor ); -void rtensor_Add( rtensor, rtensor ); -void rtensor_ScaledAdd( rtensor, real, rtensor ); -void rtensor_Sum( rtensor, rtensor, rtensor ); -void rtensor_ScaledSum( rtensor, real, rtensor, real, rtensor ); -void rtensor_Scale( rtensor, real, rtensor ); -void rtensor_Copy( rtensor, rtensor ); -void rtensor_Identity( rtensor ); -void rtensor_Transpose( rtensor, rtensor ); -real rtensor_Det( rtensor ); -real rtensor_Trace( rtensor ); - -void Print_rTensor(FILE*,rtensor); -int ivec_isZero( ivec ); -int ivec_isEqual( ivec, ivec ); void ivec_MakeZero( ivec ); void ivec_Copy( ivec, ivec ); void ivec_Scale( ivec, real, ivec ); -void ivec_rScale( ivec, real, rvec ); void ivec_Sum( ivec, ivec, ivec ); -void ivec_ScaledSum( ivec, int, ivec, int, ivec ); -void ivec_Add( ivec, ivec ); -void ivec_ScaledAdd( ivec, int, ivec ); -void ivec_Max( ivec, ivec, ivec ); -void ivec_Max3( ivec, ivec, ivec, ivec ); #endif