From 7d9670bc6c4865d96431e256a0287fc797c971ae Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Fri, 28 Apr 2017 14:48:34 -0500 Subject: [PATCH 01/26] Addition of potential, code modifications to incorporate multicomponent spline MEAM in pair_meam_spline. Backwards compatible with previous version of pair_meam_spline. --- potentials/TiO.meam.spline | 130 +++++++ src/USER-MISC/pair_meam_spline.cpp | 597 +++++++++++++++++++---------- src/USER-MISC/pair_meam_spline.h | 50 ++- 3 files changed, 566 insertions(+), 211 deletions(-) create mode 100644 potentials/TiO.meam.spline diff --git a/potentials/TiO.meam.spline b/potentials/TiO.meam.spline new file mode 100644 index 0000000000..ed2a67a962 --- /dev/null +++ b/potentials/TiO.meam.spline @@ -0,0 +1,130 @@ +# Ti-O cubic spline potential where O is in the dilute limit. DATE: 2016-06-05 CONTRIBUTOR: Pinchao Zhang, Dallas R. Trinkle +meam/spline 2 Ti O +spline3eq +13 +-20 0 +1.742692837 3.744277175966 99.4865081627958 +2.05580176725 0.910839730906 10.8702523265355 +2.3689106975 0.388045896634 -1.55322418749562 +2.68201962775 -0.018840906533 2.43630041329215 +2.995128558 -0.248098929639 2.67912713976835 +3.30823748825 -0.264489550297 -0.125056384603077 +3.6213464185 -0.227196189283 1.10662555360438 +3.93445534875 -0.129293090176 -0.592053676745914 +4.247564279 -0.059685366933 -0.470123414607672 +4.56067320925 -0.031100025561 -0.0380739973059663 +4.8737821395 -0.013847363202 -0.0711547960695406 +5.18689106975 -0.003203412728 -0.081768292420175 +5.5 0 -0.0571422964883619 +spline3eq +5 +0.155001355787331 0 +1.9 0.533321679606674 0 +2.8 0.456402081843862 -1.60311717015859 +3.7 -0.324281383502201 1.19940299483249 +4.6 -0.474029826906675 1.47909794595154 +5.5 0 -2.49521499855605 +spline3eq +13 +0 0 +1.742692837 0 0 +2.05580176725 0 0 +2.3689106975 0 0 +2.68201962775 0 0 +2.995128558 0 0 +3.30823748825 0 0 +3.6213464185 0 0 +3.93445534875 0 0 +4.247564279 0 0 +4.56067320925 0 0 +4.8737821395 0 0 +5.18689106975 0 0 +5.5 0 0 +spline3eq +11 +-1 0 +2.055801767 1.7475279661 -525.869786904802 +2.2912215903 -5.8677963945 252.796316927755 +2.5266414136 -8.3376288737 71.7318388721015 +2.7620612369 -5.8398712842 -1.93587742753693 +2.9974810602 -3.1140648231 -39.2999192667503 +3.2329008835 -1.7257245065 14.3424136002004 +3.4683207068 -0.4428977017 -29.4925534559498 +3.7037405301 -0.1466643003 -3.18010534572236 +3.9391603534 -0.2095507945 3.33490838803603 +4.1745801767 -0.1442384563 3.71918691359508 +4.41 0 -9.66717019857564 +spline3eq +5 +-61.9827585211652 0 +1.9 11.2293641315584 0 +2.8 -27.9976343076148 122.648031332411 +3.7 -8.32979773113248 -54.3340881766381 +4.6 -1.00863195297399 3.23150064581724 +5.5 0 -5.3514242228123 +spline3eq +4 +0.00776934946045395 0.105197706160344 +-55.14233165 -0.29745568008 0.00152870603877451 +-44.7409899033333 -0.15449458722 0.00038933722543571 +-34.3396481566667 0.05098657168 0.00038124926922248 +-23.93830641 0.57342694704 0.0156639264890892 +spline3eq +5 +-0.00676745157022662 -0.0159520381982146 +-23.9928 0.297607384684645 0 +-15.9241175 0.216691597077105 -0.0024248755353942 +-7.855435 0.0637598673719069 0.00306245895013358 +0.213247499999998 -0.00183450621970427 -0.00177588407633909 +8.28193 -0.111277018874367 0 +spline3eq +10 +2.77327511656661 0 +2.055801767 -0.1485215264 72.2010867146919 +2.31737934844444 1.6845304918 -47.2744689053404 +2.57895692988889 2.0113365977 -15.1859578405326 +2.84053451133333 1.1444092747 3.33978204841873 +3.10211209277778 0.2861606803 2.587867603808 +3.36368967422222 -0.3459281126 6.14070694084556 +3.62526725566667 -0.6257480601 3.7397696717154 +3.88684483711111 -0.6119510826 4.64749084871402 +4.14842241855556 -0.3112059651 2.83275746415936 +4.41 0 -15.0612086827734 +spline3eq +5 +12.3315547862781 0 +1.9 2.62105440156724 0 +2.8 10.2850803058354 -25.439802988016 +3.7 3.23933763743897 -7.20203673434025 +4.6 -5.79049355858613 39.5509978688682 +5.5 0 -41.221771373642 +spline3eq +8 +8.33642274810572 -60.4024574736564 +-1 0.07651409193 -110.652321293778 +-0.724509054371429 0.14155824541 44.8853405500508 +-0.449018108742857 0.75788697341 -25.3065115342002 +-0.173527163114286 0.63011570378 -2.48510144915082 +0.101963782514286 0.09049597305 2.68769386908235 +0.377454728142857 -0.35741586657 -1.01558570129633 +0.652945673771428 -0.65293217647 13.4224786001212 +0.9284366194 -6.00912190653 -452.752542694929 +spline3eq +5 +0.137191606537625 -1.55094230968985 +-1 0.0513843442016519 0 +-0.5 0.0179024412245673 -2.44986494990154 +0 -0.260650876879273 3.91774583656401 +0.5 -0.190163791764901 -4.84414871911743 +1 -0.763795416646599 0 +spline3eq +8 +0 0 +-1 0 0 +-0.724509054371429 0 0 +-0.449018108742857 0 0 +-0.173527163114286 0 0 +0.101963782514286 0 0 +0.377454728142857 0 0 +0.652945673771428 0 0 +0.9284366194 0 0 diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 614661ad55..4ee5989473 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -13,6 +13,8 @@ /* ---------------------------------------------------------------------- Contributing author: Alexander Stukowski (LLNL), alex@stukowski.com + Will Tipton (Cornell), wwt26@cornell.edu + Dallas R. Trinkle (UIUC), dtrinkle@illinois.edu / Pinchao Zhang (UIUC) see LLNL copyright notice at bottom of file ------------------------------------------------------------------------- */ @@ -23,12 +25,14 @@ * 25-Mar-11 - AS: Fixed calculation of per-atom virial stress. * 11-Apr-11 - AS: Adapted code to new memory management of LAMMPS. * 24-Sep-11 - AS: Adapted code to new interface of Error::one() function. + * 20-Jun-13 - WT: Added support for multiple species types + * 25-Apr-17 - DRT/PZ: Modified format of multiple species type to conform with pairing ------------------------------------------------------------------------- */ -#include -#include -#include -#include +#include "math.h" +#include "stdio.h" +#include "stdlib.h" +#include "string.h" #include "pair_meam_spline.h" #include "atom.h" #include "force.h" @@ -39,6 +43,9 @@ #include "neigh_request.h" #include "memory.h" #include "error.h" +#include + +using namespace std; using namespace LAMMPS_NS; @@ -49,7 +56,6 @@ PairMEAMSpline::PairMEAMSpline(LAMMPS *lmp) : Pair(lmp) single_enable = 0; restartinfo = 0; one_coeff = 1; - manybody_flag = 1; nelements = 0; elements = NULL; @@ -77,6 +83,15 @@ PairMEAMSpline::~PairMEAMSpline() if(allocated) { memory->destroy(setflag); memory->destroy(cutsq); + + delete[] phis; + delete[] Us; + delete[] rhos; + delete[] fs; + delete[] gs; + + delete[] zero_atom_energies; + delete [] map; } } @@ -85,11 +100,12 @@ PairMEAMSpline::~PairMEAMSpline() void PairMEAMSpline::compute(int eflag, int vflag) { - if (eflag || vflag) ev_setup(eflag, vflag); - else evflag = vflag_fdotr = - eflag_global = vflag_global = eflag_atom = vflag_atom = 0; - - double cutforcesq = cutoff*cutoff; + if (eflag || vflag) { + ev_setup(eflag, vflag); + } else { + evflag = vflag_fdotr = eflag_global = 0; + vflag_global = eflag_atom = vflag_atom = 0; + } // Grow per-atom array if necessary @@ -99,22 +115,13 @@ void PairMEAMSpline::compute(int eflag, int vflag) memory->create(Uprime_values,nmax,"pair:Uprime"); } - double** const x = atom->x; - double** forces = atom->f; - int nlocal = atom->nlocal; - bool newton_pair = force->newton_pair; - - int inum_full = listfull->inum; - int* ilist_full = listfull->ilist; - int* numneigh_full = listfull->numneigh; - int** firstneigh_full = listfull->firstneigh; - // Determine the maximum number of neighbors a single atom has int newMaxNeighbors = 0; - for(int ii = 0; ii < inum_full; ii++) { - int jnum = numneigh_full[ilist_full[ii]]; - if(jnum > newMaxNeighbors) newMaxNeighbors = jnum; + for(int ii = 0; ii < listfull->inum; ii++) { + int jnum = listfull->numneigh[listfull->ilist[ii]]; + if(jnum > newMaxNeighbors) + newMaxNeighbors = jnum; } // Allocate array for temporary bond info @@ -126,35 +133,129 @@ void PairMEAMSpline::compute(int eflag, int vflag) } // Sum three-body contributions to charge density and - // compute embedding energies + // the embedding energy - for(int ii = 0; ii < inum_full; ii++) { - int i = ilist_full[ii]; - double xtmp = x[i][0]; - double ytmp = x[i][1]; - double ztmp = x[i][2]; - int* jlist = firstneigh_full[i]; - int jnum = numneigh_full[i]; - double rho_value = 0; + for(int ii = 0; ii < listfull->inum; ii++) { + int i = listfull->ilist[ii]; int numBonds = 0; + + // compute charge density and numBonds + + double rho_value = compute_three_body_contrib_to_charge_density(i, numBonds); + //cout<<"i "<forward_comm_pair(this); + + // Compute two-body pair interactions + compute_two_body_pair_interactions(); + + if(vflag_fdotr) + virial_fdotr_compute(); +} + + +double PairMEAMSpline::pair_density(int i) +{ + double rho_value = 0; + MEAM2Body* nextTwoBodyInfo = twoBodyInfo; + + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { + int j = listfull->firstneigh[i][jj]; + j &= NEIGHMASK; + + double jdelx = atom->x[j][0] - atom->x[i][0]; + double jdely = atom->x[j][1] - atom->x[i][1]; + double jdelz = atom->x[j][2] - atom->x[i][2]; + double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; + double rij = sqrt(rij_sq); + + if(rij_sq < cutoff*cutoff) { + double rij = sqrt(rij_sq); + rho_value += rhos[i_to_potl(j)].eval(rij); + } + } + + return rho_value; +} + + + +double PairMEAMSpline::three_body_density(int i) +{ + double rho_value = 0; + int numBonds=0; + + MEAM2Body* nextTwoBodyInfo = twoBodyInfo; + + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { + int j = listfull->firstneigh[i][jj]; + j &= NEIGHMASK; + + double jdelx = atom->x[j][0] - atom->x[i][0]; + double jdely = atom->x[j][1] - atom->x[i][1]; + double jdelz = atom->x[j][2] - atom->x[i][2]; + double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; + + if(rij_sq < cutoff*cutoff) { + double rij = sqrt(rij_sq); + double partial_sum = 0; + + nextTwoBodyInfo->tag = j; + nextTwoBodyInfo->r = rij; + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->del[0] = jdelx / rij; + nextTwoBodyInfo->del[1] = jdely / rij; + nextTwoBodyInfo->del[2] = jdelz / rij; + + for(int kk = 0; kk < numBonds; kk++) { + const MEAM2Body& bondk = twoBodyInfo[kk]; + double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + + nextTwoBodyInfo->del[1]*bondk.del[1] + + nextTwoBodyInfo->del[2]*bondk.del[2]); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); + } + + rho_value += nextTwoBodyInfo->f * partial_sum; + numBonds++; + nextTwoBodyInfo++; + } + } + + return rho_value; +} + +double PairMEAMSpline::compute_three_body_contrib_to_charge_density(int i, int& numBonds) { + double rho_value = 0; MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - for(int jj = 0; jj < jnum; jj++) { - int j = jlist[jj]; + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { + int j = listfull->firstneigh[i][jj]; j &= NEIGHMASK; - double jdelx = x[j][0] - xtmp; - double jdely = x[j][1] - ytmp; - double jdelz = x[j][2] - ztmp; + double jdelx = atom->x[j][0] - atom->x[i][0]; + double jdely = atom->x[j][1] - atom->x[i][1]; + double jdelz = atom->x[j][2] - atom->x[i][2]; double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - if(rij_sq < cutforcesq) { + if(rij_sq < cutoff*cutoff) { double rij = sqrt(rij_sq); double partial_sum = 0; nextTwoBodyInfo->tag = j; nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = f.eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); nextTwoBodyInfo->del[0] = jdelx / rij; nextTwoBodyInfo->del[1] = jdely / rij; nextTwoBodyInfo->del[2] = jdelz / rij; @@ -164,31 +265,41 @@ void PairMEAMSpline::compute(int eflag, int vflag) double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + nextTwoBodyInfo->del[1]*bondk.del[1] + nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * g.eval(cos_theta); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); } rho_value += nextTwoBodyInfo->f * partial_sum; - rho_value += rho.eval(rij); + rho_value += rhos[i_to_potl(j)].eval(rij); numBonds++; nextTwoBodyInfo++; } } - // Compute embedding energy and its derivative + return rho_value; +} +double PairMEAMSpline::compute_embedding_energy_and_deriv(int eflag, int i, double rho_value) { double Uprime_i; - double embeddingEnergy = U.eval(rho_value, Uprime_i) - zero_atom_energy; + double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) + - zero_atom_energies[i_to_potl(i)]; + //cout<<"Density "<del[1] + bondj.del[2]*bondk->del[2]); double g_prime; - double g_value = g.eval(cos_theta, g_prime); + double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); double f_rik_prime = bondk->fprime; double f_rik = bondk->f; @@ -237,9 +348,9 @@ void PairMEAMSpline::compute(int eflag, int vflag) forces_i[2] -= fk[2]; int k = bondk->tag; - forces[k][0] += fk[0]; - forces[k][1] += fk[1]; - forces[k][2] += fk[2]; + atom->f[k][0] += fk[0]; + atom->f[k][1] += fk[1]; + atom->f[k][2] += fk[2]; if(evflag) { double delta_ij[3]; @@ -254,76 +365,91 @@ void PairMEAMSpline::compute(int eflag, int vflag) } } - forces[i][0] -= forces_j[0]; - forces[i][1] -= forces_j[1]; - forces[i][2] -= forces_j[2]; - forces[j][0] += forces_j[0]; - forces[j][1] += forces_j[1]; - forces[j][2] += forces_j[2]; + atom->f[i][0] -= forces_j[0]; + atom->f[i][1] -= forces_j[1]; + atom->f[i][2] -= forces_j[2]; + atom->f[j][0] += forces_j[0]; + atom->f[j][1] += forces_j[1]; + atom->f[j][2] += forces_j[2]; } - forces[i][0] += forces_i[0]; - forces[i][1] += forces_i[1]; - forces[i][2] += forces_i[2]; - } + atom->f[i][0] += forces_i[0]; + atom->f[i][1] += forces_i[1]; + atom->f[i][2] += forces_i[2]; +} - // Communicate U'(rho) values +void PairMEAMSpline::compute_two_body_pair_interactions() { + for(int ii = 0; ii < listhalf->inum; ii++) { + int i = listhalf->ilist[ii]; - comm->forward_comm_pair(this); - - int inum_half = listhalf->inum; - int* ilist_half = listhalf->ilist; - int* numneigh_half = listhalf->numneigh; - int** firstneigh_half = listhalf->firstneigh; - - // Compute two-body pair interactions - - for(int ii = 0; ii < inum_half; ii++) { - int i = ilist_half[ii]; - double xtmp = x[i][0]; - double ytmp = x[i][1]; - double ztmp = x[i][2]; - int* jlist = firstneigh_half[i]; - int jnum = numneigh_half[i]; - - for(int jj = 0; jj < jnum; jj++) { - int j = jlist[jj]; + for(int jj = 0; jj < listhalf->numneigh[i]; jj++) { + int j = listhalf->firstneigh[i][jj]; j &= NEIGHMASK; double jdel[3]; - jdel[0] = x[j][0] - xtmp; - jdel[1] = x[j][1] - ytmp; - jdel[2] = x[j][2] - ztmp; + jdel[0] = atom->x[j][0] - atom->x[i][0]; + jdel[1] = atom->x[j][1] - atom->x[i][1]; + jdel[2] = atom->x[j][2] - atom->x[i][2]; double rij_sq = jdel[0]*jdel[0] + jdel[1]*jdel[1] + jdel[2]*jdel[2]; - if(rij_sq < cutforcesq) { + if(rij_sq < cutoff*cutoff) { double rij = sqrt(rij_sq); - double rho_prime; - rho.eval(rij, rho_prime); - double fpair = rho_prime * (Uprime_values[i] + Uprime_values[j]); - +// double rho_prime; +// rhos[i_to_potl(j)].eval(rij, rho_prime); +// cout<<"rho_prime "<f[i][0] += jdel[0]*fpair; + //cout<f[i][0]<f[i][1] += jdel[1]*fpair; + //cout<f[i][1]<f[i][2] += jdel[2]*fpair; + //cout<f[i][2]<f[j][0] -= jdel[0]*fpair; + //cout<f[j][0]<f[j][1] -= jdel[1]*fpair; + //cout<f[j][1]<f[j][2] -= jdel[2]*fpair; + ////cout<f[j][2]<nlocal, force->newton_pair, pair_pot, 0.0, -fpair, jdel[0], jdel[1], jdel[2]); } } } +} - if(vflag_fdotr) virial_fdotr_compute(); +/* ---------------------------------------------------------------------- + helper functions to map atom types to potential array indices +------------------------------------------------------------------------- */ + +int PairMEAMSpline::ij_to_potl(int i, int j) { + int n = atom->ntypes; + int itype = atom->type[i]; + int jtype = atom->type[j]; + + // printf("%d %d %d\n",n,itype,jtype); + return jtype - 1 + (itype-1)*n - (itype-1)*itype/2; +} + +int PairMEAMSpline::i_to_potl(int i) { + int itype = atom->type[i]; + return itype - 1; } /* ---------------------------------------------------------------------- */ @@ -331,11 +457,23 @@ void PairMEAMSpline::compute(int eflag, int vflag) void PairMEAMSpline::allocate() { allocated = 1; - int n = atom->ntypes; + int n = nelements; memory->create(setflag,n+1,n+1,"pair:setflag"); memory->create(cutsq,n+1,n+1,"pair:cutsq"); + int nmultichoose2 = n*(n+1)/2; + //Change the functional form + //f_ij->f_i + //g_i(cos\theta_ijk)->g_jk(cos\theta_ijk) + phis = new SplineFunction[nmultichoose2]; + Us = new SplineFunction[n]; + rhos = new SplineFunction[n]; + fs = new SplineFunction[n]; + gs = new SplineFunction[nmultichoose2]; + + zero_atom_energies = new double[n]; + map = new int[n+1]; } @@ -356,7 +494,8 @@ void PairMEAMSpline::coeff(int narg, char **arg) { int i,j,n; - if (!allocated) allocate(); + if (!allocated) + allocate(); if (narg != 3 + atom->ntypes) error->all(FLERR,"Incorrect args for pair coefficients"); @@ -366,45 +505,34 @@ void PairMEAMSpline::coeff(int narg, char **arg) if (strcmp(arg[0],"*") != 0 || strcmp(arg[1],"*") != 0) error->all(FLERR,"Incorrect args for pair coefficients"); + // read potential file: also sets the number of elements. + read_file(arg[2]); + // read args that map atom types to elements in potential file // map[i] = which element the Ith atom type is, -1 if NULL // nelements = # of unique elements // elements = list of element names - if (elements) { - for (i = 0; i < nelements; i++) delete [] elements[i]; - delete [] elements; - } - elements = new char*[atom->ntypes]; - for (i = 0; i < atom->ntypes; i++) elements[i] = NULL; - - nelements = 0; - for (i = 3; i < narg; i++) { - if (strcmp(arg[i],"NULL") == 0) { - map[i-2] = -1; - continue; + if ((nelements == 1) && (strlen(elements[0]) == 0)) { + // old style: we only have one species, so we're either "NULL" or we match. + for (i = 3; i < narg; i++) + if (strcmp(arg[i],"NULL") == 0) + map[i-2] = -1; + else + map[i-2] = 0; + } else { + for (i = 3; i < narg; i++) { + if (strcmp(arg[i],"NULL") == 0) { + map[i-2] = -1; + continue; + } + for (j = 0; j < nelements; j++) + if (strcmp(arg[i],elements[j]) == 0) + break; + if (j < nelements) map[i-2] = j; + else error->all(FLERR,"No matching element in EAM potential file"); + } } - for (j = 0; j < nelements; j++) - if (strcmp(arg[i],elements[j]) == 0) break; - map[i-2] = j; - if (j == nelements) { - n = strlen(arg[i]) + 1; - elements[j] = new char[n]; - strcpy(elements[j],arg[i]); - nelements++; - } - } - - // for now, only allow single element - - if (nelements > 1) - error->all(FLERR, - "Pair meam/spline only supports single element potentials"); - - // read potential file - - read_file(arg[2]); - // clear setflag since coeff() called once with I,J = * * n = atom->ntypes; @@ -425,65 +553,134 @@ void PairMEAMSpline::coeff(int narg, char **arg) if (count == 0) error->all(FLERR,"Incorrect args for pair coefficients"); } -/* ---------------------------------------------------------------------- - set coeffs for one or more type pairs -------------------------------------------------------------------------- */ - #define MAXLINE 1024 void PairMEAMSpline::read_file(const char* filename) { - if(comm->me == 0) { - FILE *fp = force->open_potential(filename); - if(fp == NULL) { - char str[1024]; - sprintf(str,"Cannot open spline MEAM potential file %s", filename); - error->one(FLERR,str); - } + int nmultichoose2; // = (n+1)*n/2; - // Skip first line of file. - char line[MAXLINE]; - fgets(line, MAXLINE, fp); + if(comm->me == 0) { + FILE *fp = fopen(filename, "r"); + if(fp == NULL) { + char str[1024]; + sprintf(str,"Cannot open spline MEAM potential file %s", filename); + error->one(FLERR,str); + } + + // Skip first line of file. It's a comment. + char line[MAXLINE]; + fgets(line, MAXLINE, fp); + + // Second line holds potential type (currently just "meam/spline") in new potential format. + bool isNewFormat; + long loc = ftell(fp); + fgets(line, MAXLINE, fp); + if (strncmp(line, "meam/spline", 11) == 0) { + isNewFormat = true; + // parse the rest of the line! + char *linep = line+12, *word; + const char *sep = " ,;:-\t\n"; // overkill, but safe + word = strsep(&linep, sep); + if (! *word) + error->one(FLERR, "Need to include number of atomic species on meam/spline line in potential file"); + int n = atoi(word); + if (n<1) + error->one(FLERR, "Invalid number of atomic species on meam/spline line in potential file"); + nelements = n; + elements = new char*[n]; + for (int i=0; ione(FLERR, "Not enough atomic species in meam/spline\n"); + elements[i] = new char[strlen(word)+1]; + strcpy(elements[i], word); + } + } else { + isNewFormat = false; + nelements = 1; // old format only handles one species anyway; this is for backwards compatibility + elements = new char*[1]; + elements[0] = new char[1]; + strcpy(elements[0], ""); + fseek(fp, loc, SEEK_SET); + } + + nmultichoose2 = ((nelements+1)*nelements)/2; + // allocate!! + allocate(); + + // Parse spline functions. + + for (int i = 0; i < nmultichoose2; i++) + phis[i].parse(fp, error, isNewFormat); + for (int i = 0; i < nelements; i++) + rhos[i].parse(fp, error, isNewFormat); + for (int i = 0; i < nelements; i++) + Us[i].parse(fp, error, isNewFormat); + for (int i = 0; i < nelements; i++) + fs[i].parse(fp, error, isNewFormat); + for (int i = 0; i < nmultichoose2; i++) + gs[i].parse(fp, error, isNewFormat); + + fclose(fp); + } - // Parse spline functions. - phi.parse(fp, error); - rho.parse(fp, error); - U.parse(fp, error); - f.parse(fp, error); - g.parse(fp, error); - - fclose(fp); - } - - // Transfer spline functions from master processor to all other processors. - phi.communicate(world, comm->me); - rho.communicate(world, comm->me); - f.communicate(world, comm->me); - U.communicate(world, comm->me); - g.communicate(world, comm->me); - - // Calculate 'zero-point energy' of single atom in vacuum. - zero_atom_energy = U.eval(0.0); - - // Determine maximum cutoff radius of all relevant spline functions. - cutoff = 0.0; - if(phi.cutoff() > cutoff) cutoff = phi.cutoff(); - if(rho.cutoff() > cutoff) cutoff = rho.cutoff(); - if(f.cutoff() > cutoff) cutoff = f.cutoff(); - - // Set LAMMPS pair interaction flags. - for(int i = 1; i <= atom->ntypes; i++) { - for(int j = 1; j <= atom->ntypes; j++) { - setflag[i][j] = 1; - cutsq[i][j] = cutoff; - } - } - - //phi.writeGnuplot("phi.gp", "Phi(r)"); - //rho.writeGnuplot("rho.gp", "Rho(r)"); - //f.writeGnuplot("f.gp", "f(r)"); - //U.writeGnuplot("U.gp", "U(rho)"); - //g.writeGnuplot("g.gp", "g(x)"); + // Transfer spline functions from master processor to all other processors. + MPI_Bcast(&nelements, 1, MPI_INT, 0, world); + MPI_Bcast(&nmultichoose2, 1, MPI_INT, 0, world); + // allocate!! + if (!allocated) { + allocate(); + elements = new char*[nelements]; + } + for (int i = 0; i < nelements; ++i) { + int n; + if (comm->me == 0) + n = strlen(elements[i]); + MPI_Bcast(&n, 1, MPI_INT, 0, world); + if (comm->me != 0) + elements[i] = new char[n]; + MPI_Bcast(elements[i], n, MPI_CHAR, 0, world); + } + for (int i = 0; i < nmultichoose2; i++) + phis[i].communicate(world, comm->me); + for (int i = 0; i < nelements; i++) + rhos[i].communicate(world, comm->me); + for (int i = 0; i < nelements; i++) + fs[i].communicate(world, comm->me); + for (int i = 0; i < nelements; i++) + Us[i].communicate(world, comm->me); + for (int i = 0; i < nmultichoose2; i++) + gs[i].communicate(world, comm->me); + + // Calculate 'zero-point energy' of single atom in vacuum. + for (int i = 0; i < nelements; i++) + zero_atom_energies[i] = Us[i].eval(0.0); + + // Determine maximum cutoff radius of all relevant spline functions. + cutoff = 0.0; + for (int i = 0; i < nmultichoose2; i++) + if(phis[i].cutoff() > cutoff) + cutoff = phis[i].cutoff(); + for (int i = 0; i < nelements; i++) + if(rhos[i].cutoff() > cutoff) + cutoff = rhos[i].cutoff(); + for (int i = 0; i < nelements; i++) + if(fs[i].cutoff() > cutoff) + cutoff = fs[i].cutoff(); + + // Set LAMMPS pair interaction flags. + for(int i = 1; i <= atom->ntypes; i++) { + for(int j = 1; j <= atom->ntypes; j++) { + // setflag[i][j] = 1; + cutsq[i][j] = cutoff; // should this be squared? + } + } + + //phi.writeGnuplot("phi.gp", "Phi(r)"); + //rho.writeGnuplot("rho.gp", "Rho(r)"); + //f.writeGnuplot("f.gp", "f(r)"); + //U.writeGnuplot("U.gp", "U(rho)"); + //g.writeGnuplot("g.gp", "g(x)"); } /* ---------------------------------------------------------------------- @@ -495,12 +692,15 @@ void PairMEAMSpline::init_style() error->all(FLERR,"Pair style meam/spline requires newton pair on"); // Need both full and half neighbor list. - int irequest_full = neighbor->request(this,instance_me); + int irequest_full = neighbor->request(this); neighbor->requests[irequest_full]->id = 1; neighbor->requests[irequest_full]->half = 0; neighbor->requests[irequest_full]->full = 1; - int irequest_half = neighbor->request(this,instance_me); + int irequest_half = neighbor->request(this); neighbor->requests[irequest_half]->id = 2; + // neighbor->requests[irequest_half]->half = 0; + // neighbor->requests[irequest_half]->half_from_full = 1; + // neighbor->requests[irequest_half]->otherlist = irequest_full; } /* ---------------------------------------------------------------------- @@ -523,14 +723,13 @@ double PairMEAMSpline::init_one(int i, int j) /* ---------------------------------------------------------------------- */ -int PairMEAMSpline::pack_forward_comm(int n, int *list, double *buf, - int pbc_flag, int *pbc) +int PairMEAMSpline::pack_forward_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) { int* list_iter = list; int* list_iter_end = list + n; while(list_iter != list_iter_end) *buf++ = Uprime_values[*list_iter++]; - return n; + return 1; } /* ---------------------------------------------------------------------- */ @@ -563,10 +762,14 @@ double PairMEAMSpline::memory_usage() /// Parses the spline knots from a text file. -void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error) +void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error, bool isNewFormat) { char line[MAXLINE]; + // If new format, read the spline format. Should always be "spline3eq" for now. + if (isNewFormat) + fgets(line, MAXLINE, fp); + // Parse number of spline knots. fgets(line, MAXLINE, fp); int n = atoi(line); @@ -578,9 +781,11 @@ void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error) double d0 = atof(strtok(line, " \t\n\r\f")); double dN = atof(strtok(NULL, " \t\n\r\f")); init(n, d0, dN); +//printf("%s\n",line); - // Skip line. - fgets(line, MAXLINE, fp); + // Skip line in old format + if (!isNewFormat) + fgets(line, MAXLINE, fp); // Parse knot coordinates. for(int i=0; i Date: Fri, 28 Apr 2017 14:53:25 -0500 Subject: [PATCH 02/26] Cleanup on pair_meam_spline.cpp --- src/USER-MISC/pair_meam_spline.cpp | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 4ee5989473..896c7d3405 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -142,12 +142,10 @@ void PairMEAMSpline::compute(int eflag, int vflag) // compute charge density and numBonds double rho_value = compute_three_body_contrib_to_charge_density(i, numBonds); - //cout<<"i "<f[i][0] += jdel[0]*fpair; - //cout<f[i][0]<f[i][1] += jdel[1]*fpair; - //cout<f[i][1]<f[i][2] += jdel[2]*fpair; - //cout<f[i][2]<f[j][0] -= jdel[0]*fpair; - //cout<f[j][0]<f[j][1] -= jdel[1]*fpair; - //cout<f[j][1]<f[j][2] -= jdel[2]*fpair; - ////cout<f[j][2]<nlocal, force->newton_pair, pair_pot, 0.0, -fpair, jdel[0], jdel[1], jdel[2]); } @@ -443,7 +425,6 @@ int PairMEAMSpline::ij_to_potl(int i, int j) { int itype = atom->type[i]; int jtype = atom->type[j]; - // printf("%d %d %d\n",n,itype,jtype); return jtype - 1 + (itype-1)*n - (itype-1)*itype/2; } @@ -672,15 +653,10 @@ void PairMEAMSpline::read_file(const char* filename) for(int i = 1; i <= atom->ntypes; i++) { for(int j = 1; j <= atom->ntypes; j++) { // setflag[i][j] = 1; - cutsq[i][j] = cutoff; // should this be squared? + cutsq[i][j] = cutoff; } } - //phi.writeGnuplot("phi.gp", "Phi(r)"); - //rho.writeGnuplot("rho.gp", "Rho(r)"); - //f.writeGnuplot("f.gp", "f(r)"); - //U.writeGnuplot("U.gp", "U(rho)"); - //g.writeGnuplot("g.gp", "g(x)"); } /* ---------------------------------------------------------------------- @@ -781,7 +757,6 @@ void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error, bool isNewFor double d0 = atof(strtok(line, " \t\n\r\f")); double dN = atof(strtok(NULL, " \t\n\r\f")); init(n, d0, dN); -//printf("%s\n",line); // Skip line in old format if (!isNewFormat) From a0b61d17b56a0ebbbce5ac33dd6c7ea970d5ab83 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Fri, 28 Apr 2017 15:08:59 -0500 Subject: [PATCH 03/26] Updates to documentation: equation. --- doc/src/Eqs/pair_meam_spline_multicomponent.tex | 13 +++++++++++++ doc/src/pair_meam_spline.txt | 12 +++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 doc/src/Eqs/pair_meam_spline_multicomponent.tex diff --git a/doc/src/Eqs/pair_meam_spline_multicomponent.tex b/doc/src/Eqs/pair_meam_spline_multicomponent.tex new file mode 100644 index 0000000000..80296266d9 --- /dev/null +++ b/doc/src/Eqs/pair_meam_spline_multicomponent.tex @@ -0,0 +1,13 @@ +\documentclass[12pt]{article} + +\begin{document} + +$$ + E=\sum_{i Date: Fri, 28 Apr 2017 15:15:21 -0500 Subject: [PATCH 04/26] Updates to pair/meam/spline documentation. --- doc/src/Eqs/pair_meam_spline.tex | 4 ++-- doc/src/pair_meam_spline.txt | 17 +++++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/doc/src/Eqs/pair_meam_spline.tex b/doc/src/Eqs/pair_meam_spline.tex index 55d42f801c..d23c6cbfeb 100644 --- a/doc/src/Eqs/pair_meam_spline.tex +++ b/doc/src/Eqs/pair_meam_spline.tex @@ -3,11 +3,11 @@ \begin{document} $$ - E=\sum_{ij}\phi(r_{ij})+\sum_{i}U(\rho_{i}), + E=\sum_{i Date: Fri, 28 Apr 2017 15:31:49 -0500 Subject: [PATCH 05/26] Cleanup on equations; JPG to be constructed. --- doc/src/Eqs/pair_meam_spline.tex | 2 +- doc/src/Eqs/pair_meam_spline_multicomponent.tex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/Eqs/pair_meam_spline.tex b/doc/src/Eqs/pair_meam_spline.tex index d23c6cbfeb..ebdb084ce9 100644 --- a/doc/src/Eqs/pair_meam_spline.tex +++ b/doc/src/Eqs/pair_meam_spline.tex @@ -7,7 +7,7 @@ $$ $$ $$ - n_{i}=\sum_{j}\rho(r_{ij})+\sum_{j Date: Fri, 28 Apr 2017 20:22:22 -0500 Subject: [PATCH 06/26] Updated version of equations, documentation. --- doc/src/Eqs/pair_meam_spline.jpg | Bin 10530 -> 21186 bytes doc/src/Eqs/pair_meam_spline.tex | 1 + .../Eqs/pair_meam_spline_multicomponent.jpg | Bin 0 -> 22975 bytes .../Eqs/pair_meam_spline_multicomponent.tex | 1 + doc/src/pair_meam_spline.txt | 17 +++++++++++++---- 5 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 doc/src/Eqs/pair_meam_spline_multicomponent.jpg diff --git a/doc/src/Eqs/pair_meam_spline.jpg b/doc/src/Eqs/pair_meam_spline.jpg index 29f1c7254365939cc3e496ac40767b5a4a54a6a6..fd396d75bc1f0f6558f3538127a6861c696cea91 100644 GIT binary patch literal 21186 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 X{*Ac)=jr{p{%-{5_f!Aa`1a<%2JSDR literal 10530 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 Z;S?0=3=bH{908|HyZ_(mjc0#m{}0GM@OA(I diff --git a/doc/src/Eqs/pair_meam_spline.tex b/doc/src/Eqs/pair_meam_spline.tex index ebdb084ce9..b4f58381a4 100644 --- a/doc/src/Eqs/pair_meam_spline.tex +++ b/doc/src/Eqs/pair_meam_spline.tex @@ -1,4 +1,5 @@ \documentclass[12pt]{article} +\usepackage{amsmath} \begin{document} diff --git a/doc/src/Eqs/pair_meam_spline_multicomponent.jpg b/doc/src/Eqs/pair_meam_spline_multicomponent.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3323284005f2889801c547af712788bbd2fb49b6 GIT binary patch literal 22975 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 Date: Mon, 1 May 2017 13:38:37 -0500 Subject: [PATCH 07/26] Small error in elements allocation causing seg. fault for parallel runs; fixed. --- src/USER-MISC/pair_meam_spline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 896c7d3405..5941a9f600 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -619,7 +619,7 @@ void PairMEAMSpline::read_file(const char* filename) n = strlen(elements[i]); MPI_Bcast(&n, 1, MPI_INT, 0, world); if (comm->me != 0) - elements[i] = new char[n]; + elements[i] = new char[n+1]; MPI_Bcast(elements[i], n, MPI_CHAR, 0, world); } for (int i = 0; i < nmultichoose2; i++) From c76d27373ecd7be40cbc1ccb163178681dfa49bc Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Mon, 1 May 2017 20:33:07 -0500 Subject: [PATCH 08/26] Another fix for seg fault in parallel allocation. --- src/USER-MISC/pair_meam_spline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 5941a9f600..92a56d12e5 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -609,7 +609,7 @@ void PairMEAMSpline::read_file(const char* filename) MPI_Bcast(&nelements, 1, MPI_INT, 0, world); MPI_Bcast(&nmultichoose2, 1, MPI_INT, 0, world); // allocate!! - if (!allocated) { + if (comm->me != 0) { allocate(); elements = new char*[nelements]; } From 408cc198854ca379e65e29e9997a814cb712daa3 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Mon, 1 May 2017 20:36:09 -0500 Subject: [PATCH 09/26] Fix for seg fault. --- src/USER-MISC/pair_meam_spline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 92a56d12e5..fae39c366d 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -620,7 +620,7 @@ void PairMEAMSpline::read_file(const char* filename) MPI_Bcast(&n, 1, MPI_INT, 0, world); if (comm->me != 0) elements[i] = new char[n+1]; - MPI_Bcast(elements[i], n, MPI_CHAR, 0, world); + MPI_Bcast(elements[i], n+1, MPI_CHAR, 0, world); } for (int i = 0; i < nmultichoose2; i++) phis[i].communicate(world, comm->me); From f58fc9488f89dd612aa261682ec3e8ccdc756226 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Mon, 1 May 2017 21:56:19 -0500 Subject: [PATCH 10/26] Fixed neighbor list building that caused error in parallel runs with pair_meam_spline. --- src/USER-MISC/pair_meam_spline.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index fae39c366d..ad32eb0dba 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -674,9 +674,9 @@ void PairMEAMSpline::init_style() neighbor->requests[irequest_full]->full = 1; int irequest_half = neighbor->request(this); neighbor->requests[irequest_half]->id = 2; - // neighbor->requests[irequest_half]->half = 0; - // neighbor->requests[irequest_half]->half_from_full = 1; - // neighbor->requests[irequest_half]->otherlist = irequest_full; + neighbor->requests[irequest_half]->half = 0; + neighbor->requests[irequest_half]->halffull = 1; + neighbor->requests[irequest_half]->halffulllist = irequest_full; } /* ---------------------------------------------------------------------- From 50c7234f269022a1191814864b9fa7977c6b0c94 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Tue, 2 May 2017 09:43:57 -0500 Subject: [PATCH 11/26] Fix to communication for mpi. Tested, and now working correctly with MPI. --- src/USER-MISC/pair_meam_spline.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index ad32eb0dba..f3ac8905ed 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -668,15 +668,15 @@ void PairMEAMSpline::init_style() error->all(FLERR,"Pair style meam/spline requires newton pair on"); // Need both full and half neighbor list. - int irequest_full = neighbor->request(this); + int irequest_full = neighbor->request(this,instance_me); neighbor->requests[irequest_full]->id = 1; neighbor->requests[irequest_full]->half = 0; neighbor->requests[irequest_full]->full = 1; - int irequest_half = neighbor->request(this); + int irequest_half = neighbor->request(this,instance_me); neighbor->requests[irequest_half]->id = 2; - neighbor->requests[irequest_half]->half = 0; - neighbor->requests[irequest_half]->halffull = 1; - neighbor->requests[irequest_half]->halffulllist = irequest_full; + // neighbor->requests[irequest_half]->half = 1; + // neighbor->requests[irequest_half]->halffull = 1; + // neighbor->requests[irequest_half]->halffulllist = irequest_full; } /* ---------------------------------------------------------------------- @@ -705,7 +705,7 @@ int PairMEAMSpline::pack_forward_comm(int n, int *list, double *buf, int pbc_fla int* list_iter_end = list + n; while(list_iter != list_iter_end) *buf++ = Uprime_values[*list_iter++]; - return 1; + return n; } /* ---------------------------------------------------------------------- */ From 11cb0212b7fa97b4a7955130e93690bc8eb4a7bc Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Wed, 3 May 2017 16:49:43 -0500 Subject: [PATCH 12/26] Cleanup: two space indent + no trailing spaces on lines. --- src/USER-MISC/pair_meam_spline.cpp | 712 +++++++++++++++-------------- src/USER-MISC/pair_meam_spline.h | 405 ++++++++-------- 2 files changed, 558 insertions(+), 559 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index f3ac8905ed..59fcd2c889 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -14,7 +14,8 @@ /* ---------------------------------------------------------------------- Contributing author: Alexander Stukowski (LLNL), alex@stukowski.com Will Tipton (Cornell), wwt26@cornell.edu - Dallas R. Trinkle (UIUC), dtrinkle@illinois.edu / Pinchao Zhang (UIUC) + Dallas R. Trinkle (UIUC), dtrinkle@illinois.edu + Pinchao Zhang (UIUC) see LLNL copyright notice at bottom of file ------------------------------------------------------------------------- */ @@ -26,7 +27,8 @@ * 11-Apr-11 - AS: Adapted code to new memory management of LAMMPS. * 24-Sep-11 - AS: Adapted code to new interface of Error::one() function. * 20-Jun-13 - WT: Added support for multiple species types - * 25-Apr-17 - DRT/PZ: Modified format of multiple species type to conform with pairing + * 25-Apr-17 - DRT/PZ: Modified format of multiple species type to + conform with pairing ------------------------------------------------------------------------- */ #include "math.h" @@ -166,227 +168,227 @@ void PairMEAMSpline::compute(int eflag, int vflag) double PairMEAMSpline::pair_density(int i) { - double rho_value = 0; - MEAM2Body* nextTwoBodyInfo = twoBodyInfo; + double rho_value = 0; + MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - for(int jj = 0; jj < listfull->numneigh[i]; jj++) { - int j = listfull->firstneigh[i][jj]; - j &= NEIGHMASK; - - double jdelx = atom->x[j][0] - atom->x[i][0]; - double jdely = atom->x[j][1] - atom->x[i][1]; - double jdelz = atom->x[j][2] - atom->x[i][2]; - double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - double rij = sqrt(rij_sq); - - if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - rho_value += rhos[i_to_potl(j)].eval(rij); - } + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { + int j = listfull->firstneigh[i][jj]; + j &= NEIGHMASK; + + double jdelx = atom->x[j][0] - atom->x[i][0]; + double jdely = atom->x[j][1] - atom->x[i][1]; + double jdelz = atom->x[j][2] - atom->x[i][2]; + double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; + double rij = sqrt(rij_sq); + + if(rij_sq < cutoff*cutoff) { + double rij = sqrt(rij_sq); + rho_value += rhos[i_to_potl(j)].eval(rij); } - - return rho_value; + } + + return rho_value; } double PairMEAMSpline::three_body_density(int i) { - double rho_value = 0; - int numBonds=0; - - MEAM2Body* nextTwoBodyInfo = twoBodyInfo; + double rho_value = 0; + int numBonds=0; + + MEAM2Body* nextTwoBodyInfo = twoBodyInfo; + + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { + int j = listfull->firstneigh[i][jj]; + j &= NEIGHMASK; - for(int jj = 0; jj < listfull->numneigh[i]; jj++) { - int j = listfull->firstneigh[i][jj]; - j &= NEIGHMASK; - - double jdelx = atom->x[j][0] - atom->x[i][0]; - double jdely = atom->x[j][1] - atom->x[i][1]; - double jdelz = atom->x[j][2] - atom->x[i][2]; - double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - - if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - double partial_sum = 0; - - nextTwoBodyInfo->tag = j; - nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); - nextTwoBodyInfo->del[0] = jdelx / rij; - nextTwoBodyInfo->del[1] = jdely / rij; - nextTwoBodyInfo->del[2] = jdelz / rij; - - for(int kk = 0; kk < numBonds; kk++) { - const MEAM2Body& bondk = twoBodyInfo[kk]; - double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + - nextTwoBodyInfo->del[1]*bondk.del[1] + - nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); - } - - rho_value += nextTwoBodyInfo->f * partial_sum; - numBonds++; - nextTwoBodyInfo++; - } + double jdelx = atom->x[j][0] - atom->x[i][0]; + double jdely = atom->x[j][1] - atom->x[i][1]; + double jdelz = atom->x[j][2] - atom->x[i][2]; + double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; + + if(rij_sq < cutoff*cutoff) { + double rij = sqrt(rij_sq); + double partial_sum = 0; + + nextTwoBodyInfo->tag = j; + nextTwoBodyInfo->r = rij; + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->del[0] = jdelx / rij; + nextTwoBodyInfo->del[1] = jdely / rij; + nextTwoBodyInfo->del[2] = jdelz / rij; + + for(int kk = 0; kk < numBonds; kk++) { + const MEAM2Body& bondk = twoBodyInfo[kk]; + double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + + nextTwoBodyInfo->del[1]*bondk.del[1] + + nextTwoBodyInfo->del[2]*bondk.del[2]); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); + } + + rho_value += nextTwoBodyInfo->f * partial_sum; + numBonds++; + nextTwoBodyInfo++; } - - return rho_value; + } + + return rho_value; } double PairMEAMSpline::compute_three_body_contrib_to_charge_density(int i, int& numBonds) { - double rho_value = 0; - MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - - for(int jj = 0; jj < listfull->numneigh[i]; jj++) { - int j = listfull->firstneigh[i][jj]; - j &= NEIGHMASK; - - double jdelx = atom->x[j][0] - atom->x[i][0]; - double jdely = atom->x[j][1] - atom->x[i][1]; - double jdelz = atom->x[j][2] - atom->x[i][2]; - double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - - if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - double partial_sum = 0; - - nextTwoBodyInfo->tag = j; - nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); - nextTwoBodyInfo->del[0] = jdelx / rij; - nextTwoBodyInfo->del[1] = jdely / rij; - nextTwoBodyInfo->del[2] = jdelz / rij; - - for(int kk = 0; kk < numBonds; kk++) { - const MEAM2Body& bondk = twoBodyInfo[kk]; - double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + - nextTwoBodyInfo->del[1]*bondk.del[1] + - nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); - } - - rho_value += nextTwoBodyInfo->f * partial_sum; - rho_value += rhos[i_to_potl(j)].eval(rij); - - numBonds++; - nextTwoBodyInfo++; + double rho_value = 0; + MEAM2Body* nextTwoBodyInfo = twoBodyInfo; + + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { + int j = listfull->firstneigh[i][jj]; + j &= NEIGHMASK; + + double jdelx = atom->x[j][0] - atom->x[i][0]; + double jdely = atom->x[j][1] - atom->x[i][1]; + double jdelz = atom->x[j][2] - atom->x[i][2]; + double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; + + if(rij_sq < cutoff*cutoff) { + double rij = sqrt(rij_sq); + double partial_sum = 0; + + nextTwoBodyInfo->tag = j; + nextTwoBodyInfo->r = rij; + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->del[0] = jdelx / rij; + nextTwoBodyInfo->del[1] = jdely / rij; + nextTwoBodyInfo->del[2] = jdelz / rij; + + for(int kk = 0; kk < numBonds; kk++) { + const MEAM2Body& bondk = twoBodyInfo[kk]; + double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + + nextTwoBodyInfo->del[1]*bondk.del[1] + + nextTwoBodyInfo->del[2]*bondk.del[2]); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); } + + rho_value += nextTwoBodyInfo->f * partial_sum; + rho_value += rhos[i_to_potl(j)].eval(rij); + + numBonds++; + nextTwoBodyInfo++; } - - return rho_value; + } + + return rho_value; } double PairMEAMSpline::compute_embedding_energy_and_deriv(int eflag, int i, double rho_value) { - double Uprime_i; - double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) - - zero_atom_energies[i_to_potl(i)]; - - Uprime_values[i] = Uprime_i; - if(eflag) { - if(eflag_global) - eng_vdwl += embeddingEnergy; - if(eflag_atom) - eatom[i] += embeddingEnergy; - } - return Uprime_i; -} + double Uprime_i; + double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) + - zero_atom_energies[i_to_potl(i)]; + + Uprime_values[i] = Uprime_i; + if(eflag) { + if(eflag_global) + eng_vdwl += embeddingEnergy; + if(eflag_atom) + eatom[i] += embeddingEnergy; + } + return Uprime_i; +} void PairMEAMSpline::compute_three_body_contrib_to_forces(int i, int numBonds, double Uprime_i) { - double forces_i[3] = {0, 0, 0}; - - for(int jj = 0; jj < numBonds; jj++) { - const MEAM2Body bondj = twoBodyInfo[jj]; - double rij = bondj.r; - int j = bondj.tag; - - double f_rij_prime = bondj.fprime; - double f_rij = bondj.f; - - double forces_j[3] = {0, 0, 0}; - - MEAM2Body const* bondk = twoBodyInfo; - for(int kk = 0; kk < jj; kk++, ++bondk) { - double rik = bondk->r; - - double cos_theta = (bondj.del[0]*bondk->del[0] + - bondj.del[1]*bondk->del[1] + - bondj.del[2]*bondk->del[2]); - double g_prime; - double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); - double f_rik_prime = bondk->fprime; - double f_rik = bondk->f; - - double fij = -Uprime_i * g_value * f_rik * f_rij_prime; - double fik = -Uprime_i * g_value * f_rij * f_rik_prime; - - double prefactor = Uprime_i * f_rij * f_rik * g_prime; - double prefactor_ij = prefactor / rij; - double prefactor_ik = prefactor / rik; - fij += prefactor_ij * cos_theta; - fik += prefactor_ik * cos_theta; - - double fj[3], fk[3]; - - fj[0] = bondj.del[0] * fij - bondk->del[0] * prefactor_ij; - fj[1] = bondj.del[1] * fij - bondk->del[1] * prefactor_ij; - fj[2] = bondj.del[2] * fij - bondk->del[2] * prefactor_ij; - forces_j[0] += fj[0]; - forces_j[1] += fj[1]; - forces_j[2] += fj[2]; - - fk[0] = bondk->del[0] * fik - bondj.del[0] * prefactor_ik; - fk[1] = bondk->del[1] * fik - bondj.del[1] * prefactor_ik; - fk[2] = bondk->del[2] * fik - bondj.del[2] * prefactor_ik; - forces_i[0] -= fk[0]; - forces_i[1] -= fk[1]; - forces_i[2] -= fk[2]; - - int k = bondk->tag; - atom->f[k][0] += fk[0]; - atom->f[k][1] += fk[1]; - atom->f[k][2] += fk[2]; - - if(evflag) { - double delta_ij[3]; - double delta_ik[3]; - delta_ij[0] = bondj.del[0] * rij; - delta_ij[1] = bondj.del[1] * rij; - delta_ij[2] = bondj.del[2] * rij; - delta_ik[0] = bondk->del[0] * rik; - delta_ik[1] = bondk->del[1] * rik; - delta_ik[2] = bondk->del[2] * rik; - ev_tally3(i, j, k, 0.0, 0.0, fj, fk, delta_ij, delta_ik); - } + double forces_i[3] = {0, 0, 0}; + + for(int jj = 0; jj < numBonds; jj++) { + const MEAM2Body bondj = twoBodyInfo[jj]; + double rij = bondj.r; + int j = bondj.tag; + + double f_rij_prime = bondj.fprime; + double f_rij = bondj.f; + + double forces_j[3] = {0, 0, 0}; + + MEAM2Body const* bondk = twoBodyInfo; + for(int kk = 0; kk < jj; kk++, ++bondk) { + double rik = bondk->r; + + double cos_theta = (bondj.del[0]*bondk->del[0] + + bondj.del[1]*bondk->del[1] + + bondj.del[2]*bondk->del[2]); + double g_prime; + double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); + double f_rik_prime = bondk->fprime; + double f_rik = bondk->f; + + double fij = -Uprime_i * g_value * f_rik * f_rij_prime; + double fik = -Uprime_i * g_value * f_rij * f_rik_prime; + + double prefactor = Uprime_i * f_rij * f_rik * g_prime; + double prefactor_ij = prefactor / rij; + double prefactor_ik = prefactor / rik; + fij += prefactor_ij * cos_theta; + fik += prefactor_ik * cos_theta; + + double fj[3], fk[3]; + + fj[0] = bondj.del[0] * fij - bondk->del[0] * prefactor_ij; + fj[1] = bondj.del[1] * fij - bondk->del[1] * prefactor_ij; + fj[2] = bondj.del[2] * fij - bondk->del[2] * prefactor_ij; + forces_j[0] += fj[0]; + forces_j[1] += fj[1]; + forces_j[2] += fj[2]; + + fk[0] = bondk->del[0] * fik - bondj.del[0] * prefactor_ik; + fk[1] = bondk->del[1] * fik - bondj.del[1] * prefactor_ik; + fk[2] = bondk->del[2] * fik - bondj.del[2] * prefactor_ik; + forces_i[0] -= fk[0]; + forces_i[1] -= fk[1]; + forces_i[2] -= fk[2]; + + int k = bondk->tag; + atom->f[k][0] += fk[0]; + atom->f[k][1] += fk[1]; + atom->f[k][2] += fk[2]; + + if(evflag) { + double delta_ij[3]; + double delta_ik[3]; + delta_ij[0] = bondj.del[0] * rij; + delta_ij[1] = bondj.del[1] * rij; + delta_ij[2] = bondj.del[2] * rij; + delta_ik[0] = bondk->del[0] * rik; + delta_ik[1] = bondk->del[1] * rik; + delta_ik[2] = bondk->del[2] * rik; + ev_tally3(i, j, k, 0.0, 0.0, fj, fk, delta_ij, delta_ik); } - - atom->f[i][0] -= forces_j[0]; - atom->f[i][1] -= forces_j[1]; - atom->f[i][2] -= forces_j[2]; - atom->f[j][0] += forces_j[0]; - atom->f[j][1] += forces_j[1]; - atom->f[j][2] += forces_j[2]; } - - atom->f[i][0] += forces_i[0]; - atom->f[i][1] += forces_i[1]; - atom->f[i][2] += forces_i[2]; + + atom->f[i][0] -= forces_j[0]; + atom->f[i][1] -= forces_j[1]; + atom->f[i][2] -= forces_j[2]; + atom->f[j][0] += forces_j[0]; + atom->f[j][1] += forces_j[1]; + atom->f[j][2] += forces_j[2]; + } + + atom->f[i][0] += forces_i[0]; + atom->f[i][1] += forces_i[1]; + atom->f[i][2] += forces_i[2]; } void PairMEAMSpline::compute_two_body_pair_interactions() { for(int ii = 0; ii < listhalf->inum; ii++) { int i = listhalf->ilist[ii]; - + for(int jj = 0; jj < listhalf->numneigh[i]; jj++) { int j = listhalf->firstneigh[i][jj]; j &= NEIGHMASK; - + double jdel[3]; jdel[0] = atom->x[j][0] - atom->x[i][0]; - jdel[1] = atom->x[j][1] - atom->x[i][1]; + jdel[1] = atom->x[j][1] - atom->x[i][1]; jdel[2] = atom->x[j][2] - atom->x[i][2]; double rij_sq = jdel[0]*jdel[0] + jdel[1]*jdel[1] + jdel[2]*jdel[2]; - + if(rij_sq < cutoff*cutoff) { double rij = sqrt(rij_sq); @@ -421,16 +423,16 @@ void PairMEAMSpline::compute_two_body_pair_interactions() { ------------------------------------------------------------------------- */ int PairMEAMSpline::ij_to_potl(int i, int j) { - int n = atom->ntypes; - int itype = atom->type[i]; - int jtype = atom->type[j]; - - return jtype - 1 + (itype-1)*n - (itype-1)*itype/2; + int n = atom->ntypes; + int itype = atom->type[i]; + int jtype = atom->type[j]; + + return jtype - 1 + (itype-1)*n - (itype-1)*itype/2; } int PairMEAMSpline::i_to_potl(int i) { - int itype = atom->type[i]; - return itype - 1; + int itype = atom->type[i]; + return itype - 1; } /* ---------------------------------------------------------------------- */ @@ -475,7 +477,7 @@ void PairMEAMSpline::coeff(int narg, char **arg) { int i,j,n; - if (!allocated) + if (!allocated) allocate(); if (narg != 3 + atom->ntypes) @@ -495,32 +497,32 @@ void PairMEAMSpline::coeff(int narg, char **arg) // elements = list of element names if ((nelements == 1) && (strlen(elements[0]) == 0)) { - // old style: we only have one species, so we're either "NULL" or we match. - for (i = 3; i < narg; i++) - if (strcmp(arg[i],"NULL") == 0) - map[i-2] = -1; - else - map[i-2] = 0; - } else { - for (i = 3; i < narg; i++) { - if (strcmp(arg[i],"NULL") == 0) { - map[i-2] = -1; - continue; - } - for (j = 0; j < nelements; j++) - if (strcmp(arg[i],elements[j]) == 0) - break; - if (j < nelements) map[i-2] = j; - else error->all(FLERR,"No matching element in EAM potential file"); + // old style: we only have one species, so we're either "NULL" or we match. + for (i = 3; i < narg; i++) + if (strcmp(arg[i],"NULL") == 0) + map[i-2] = -1; + else + map[i-2] = 0; + } else { + for (i = 3; i < narg; i++) { + if (strcmp(arg[i],"NULL") == 0) { + map[i-2] = -1; + continue; } + for (j = 0; j < nelements; j++) + if (strcmp(arg[i],elements[j]) == 0) + break; + if (j < nelements) map[i-2] = j; + else error->all(FLERR,"No matching element in EAM potential file"); } + } // clear setflag since coeff() called once with I,J = * * - + n = atom->ntypes; 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; @@ -591,11 +593,11 @@ void PairMEAMSpline::read_file(const char* filename) // Parse spline functions. - for (int i = 0; i < nmultichoose2; i++) + for (int i = 0; i < nmultichoose2; i++) phis[i].parse(fp, error, isNewFormat); - for (int i = 0; i < nelements; i++) + for (int i = 0; i < nelements; i++) rhos[i].parse(fp, error, isNewFormat); - for (int i = 0; i < nelements; i++) + for (int i = 0; i < nelements; i++) Us[i].parse(fp, error, isNewFormat); for (int i = 0; i < nelements; i++) fs[i].parse(fp, error, isNewFormat); @@ -640,10 +642,10 @@ void PairMEAMSpline::read_file(const char* filename) // Determine maximum cutoff radius of all relevant spline functions. cutoff = 0.0; for (int i = 0; i < nmultichoose2; i++) - if(phis[i].cutoff() > cutoff) + if(phis[i].cutoff() > cutoff) cutoff = phis[i].cutoff(); for (int i = 0; i < nelements; i++) - if(rhos[i].cutoff() > cutoff) + if(rhos[i].cutoff() > cutoff) cutoff = rhos[i].cutoff(); for (int i = 0; i < nelements; i++) if(fs[i].cutoff() > cutoff) @@ -664,19 +666,19 @@ void PairMEAMSpline::read_file(const char* filename) ------------------------------------------------------------------------- */ void PairMEAMSpline::init_style() { - if(force->newton_pair == 0) - error->all(FLERR,"Pair style meam/spline requires newton pair on"); + if(force->newton_pair == 0) + error->all(FLERR,"Pair style meam/spline requires newton pair on"); - // Need both full and half neighbor list. - int irequest_full = neighbor->request(this,instance_me); - neighbor->requests[irequest_full]->id = 1; - neighbor->requests[irequest_full]->half = 0; - neighbor->requests[irequest_full]->full = 1; - int irequest_half = neighbor->request(this,instance_me); - neighbor->requests[irequest_half]->id = 2; - // neighbor->requests[irequest_half]->half = 1; - // neighbor->requests[irequest_half]->halffull = 1; - // neighbor->requests[irequest_half]->halffulllist = irequest_full; + // Need both full and half neighbor list. + int irequest_full = neighbor->request(this,instance_me); + neighbor->requests[irequest_full]->id = 1; + neighbor->requests[irequest_full]->half = 0; + neighbor->requests[irequest_full]->full = 1; + int irequest_half = neighbor->request(this,instance_me); + neighbor->requests[irequest_half]->id = 2; + // neighbor->requests[irequest_half]->half = 1; + // neighbor->requests[irequest_half]->halffull = 1; + // neighbor->requests[irequest_half]->halffulllist = irequest_full; } /* ---------------------------------------------------------------------- @@ -685,8 +687,8 @@ void PairMEAMSpline::init_style() ------------------------------------------------------------------------- */ void PairMEAMSpline::init_list(int id, NeighList *ptr) { - if(id == 1) listfull = ptr; - else if(id == 2) listhalf = ptr; + if(id == 1) listfull = ptr; + else if(id == 2) listhalf = ptr; } /* ---------------------------------------------------------------------- @@ -694,32 +696,32 @@ void PairMEAMSpline::init_list(int id, NeighList *ptr) ------------------------------------------------------------------------- */ double PairMEAMSpline::init_one(int i, int j) { - return cutoff; + return cutoff; } /* ---------------------------------------------------------------------- */ int PairMEAMSpline::pack_forward_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) { - int* list_iter = list; - int* list_iter_end = list + n; - while(list_iter != list_iter_end) - *buf++ = Uprime_values[*list_iter++]; - return n; + int* list_iter = list; + int* list_iter_end = list + n; + while(list_iter != list_iter_end) + *buf++ = Uprime_values[*list_iter++]; + return n; } /* ---------------------------------------------------------------------- */ void PairMEAMSpline::unpack_forward_comm(int n, int first, double *buf) { - memcpy(&Uprime_values[first], buf, n * sizeof(buf[0])); + memcpy(&Uprime_values[first], buf, n * sizeof(buf[0])); } /* ---------------------------------------------------------------------- */ int PairMEAMSpline::pack_reverse_comm(int n, int first, double *buf) { - return 0; + return 0; } /* ---------------------------------------------------------------------- */ @@ -733,121 +735,121 @@ void PairMEAMSpline::unpack_reverse_comm(int n, int *list, double *buf) ------------------------------------------------------------------------- */ double PairMEAMSpline::memory_usage() { - return nmax * sizeof(double); // The Uprime_values array. + return nmax * sizeof(double); // The Uprime_values array. } /// Parses the spline knots from a text file. void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error, bool isNewFormat) { - char line[MAXLINE]; - - // If new format, read the spline format. Should always be "spline3eq" for now. - if (isNewFormat) - fgets(line, MAXLINE, fp); - - // Parse number of spline knots. - fgets(line, MAXLINE, fp); - int n = atoi(line); - if(n < 2) - error->one(FLERR,"Invalid number of spline knots in MEAM potential file"); - - // Parse first derivatives at beginning and end of spline. - fgets(line, MAXLINE, fp); - double d0 = atof(strtok(line, " \t\n\r\f")); - double dN = atof(strtok(NULL, " \t\n\r\f")); - init(n, d0, dN); - - // Skip line in old format - if (!isNewFormat) - fgets(line, MAXLINE, fp); - - // Parse knot coordinates. - for(int i=0; ione(FLERR,"Invalid knot line in MEAM potential file"); - } - setKnot(i, x, y); - } - - prepareSpline(error); + char line[MAXLINE]; + + // If new format, read the spline format. Should always be "spline3eq" for now. + if (isNewFormat) + fgets(line, MAXLINE, fp); + + // Parse number of spline knots. + fgets(line, MAXLINE, fp); + int n = atoi(line); + if(n < 2) + error->one(FLERR,"Invalid number of spline knots in MEAM potential file"); + + // Parse first derivatives at beginning and end of spline. + fgets(line, MAXLINE, fp); + double d0 = atof(strtok(line, " \t\n\r\f")); + double dN = atof(strtok(NULL, " \t\n\r\f")); + init(n, d0, dN); + + // Skip line in old format + if (!isNewFormat) + fgets(line, MAXLINE, fp); + + // Parse knot coordinates. + for(int i=0; ione(FLERR,"Invalid knot line in MEAM potential file"); + } + setKnot(i, x, y); + } + + prepareSpline(error); } /// Calculates the second derivatives at the knots of the cubic spline. void PairMEAMSpline::SplineFunction::prepareSpline(Error* error) { - xmin = X[0]; - xmax = X[N-1]; - - isGridSpline = true; - h = (xmax-xmin)/(N-1); - hsq = h*h; - - double* u = new double[N]; - Y2[0] = -0.5; - u[0] = (3.0/(X[1]-X[0])) * ((Y[1]-Y[0])/(X[1]-X[0]) - deriv0); - for(int i = 1; i <= N-2; i++) { - double sig = (X[i]-X[i-1]) / (X[i+1]-X[i-1]); - double p = sig * Y2[i-1] + 2.0; - Y2[i] = (sig - 1.0) / p; - u[i] = (Y[i+1]-Y[i]) / (X[i+1]-X[i]) - (Y[i]-Y[i-1])/(X[i]-X[i-1]); - u[i] = (6.0 * u[i]/(X[i+1]-X[i-1]) - sig*u[i-1])/p; - - if(fabs(h*i+xmin - X[i]) > 1e-8) - isGridSpline = false; - } - - double qn = 0.5; - double un = (3.0/(X[N-1]-X[N-2])) * (derivN - (Y[N-1]-Y[N-2])/(X[N-1]-X[N-2])); - Y2[N-1] = (un - qn*u[N-2]) / (qn * Y2[N-2] + 1.0); - for(int k = N-2; k >= 0; k--) { - Y2[k] = Y2[k] * Y2[k+1] + u[k]; - } - - delete[] u; - + xmin = X[0]; + xmax = X[N-1]; + + isGridSpline = true; + h = (xmax-xmin)/(N-1); + hsq = h*h; + + double* u = new double[N]; + Y2[0] = -0.5; + u[0] = (3.0/(X[1]-X[0])) * ((Y[1]-Y[0])/(X[1]-X[0]) - deriv0); + for(int i = 1; i <= N-2; i++) { + double sig = (X[i]-X[i-1]) / (X[i+1]-X[i-1]); + double p = sig * Y2[i-1] + 2.0; + Y2[i] = (sig - 1.0) / p; + u[i] = (Y[i+1]-Y[i]) / (X[i+1]-X[i]) - (Y[i]-Y[i-1])/(X[i]-X[i-1]); + u[i] = (6.0 * u[i]/(X[i+1]-X[i-1]) - sig*u[i-1])/p; + + if(fabs(h*i+xmin - X[i]) > 1e-8) + isGridSpline = false; + } + + double qn = 0.5; + double un = (3.0/(X[N-1]-X[N-2])) * (derivN - (Y[N-1]-Y[N-2])/(X[N-1]-X[N-2])); + Y2[N-1] = (un - qn*u[N-2]) / (qn * Y2[N-2] + 1.0); + for(int k = N-2; k >= 0; k--) { + Y2[k] = Y2[k] * Y2[k+1] + u[k]; + } + + delete[] u; + #if !SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES - if(!isGridSpline) - error->one(FLERR,"Support for MEAM potentials with non-uniform cubic splines has not been enabled in the MEAM potential code. Set SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES in pair_spline_meam.h to 1 to enable it"); + if(!isGridSpline) + error->one(FLERR,"Support for MEAM potentials with non-uniform cubic splines has not been enabled in the MEAM potential code. Set SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES in pair_spline_meam.h to 1 to enable it"); #endif - // Shift the spline to X=0 to speed up interpolation. - for(int i = 0; i < N; i++) { - Xs[i] = X[i] - xmin; + // Shift the spline to X=0 to speed up interpolation. + for(int i = 0; i < N; i++) { + Xs[i] = X[i] - xmin; #if !SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES - if(i < N-1) Ydelta[i] = (Y[i+1]-Y[i])/h; - Y2[i] /= h*6.0; + if(i < N-1) Ydelta[i] = (Y[i+1]-Y[i])/h; + Y2[i] /= h*6.0; #endif - } - xmax_shifted = xmax - xmin; + } + xmax_shifted = xmax - xmin; } /// Broadcasts the spline function parameters to all processors. void PairMEAMSpline::SplineFunction::communicate(MPI_Comm& world, int me) { - MPI_Bcast(&N, 1, MPI_INT, 0, world); - MPI_Bcast(&deriv0, 1, MPI_DOUBLE, 0, world); - MPI_Bcast(&derivN, 1, MPI_DOUBLE, 0, world); - MPI_Bcast(&xmin, 1, MPI_DOUBLE, 0, world); - MPI_Bcast(&xmax, 1, MPI_DOUBLE, 0, world); - MPI_Bcast(&xmax_shifted, 1, MPI_DOUBLE, 0, world); - MPI_Bcast(&isGridSpline, 1, MPI_INT, 0, world); - MPI_Bcast(&h, 1, MPI_DOUBLE, 0, world); - MPI_Bcast(&hsq, 1, MPI_DOUBLE, 0, world); - if(me != 0) { - X = new double[N]; - Xs = new double[N]; - Y = new double[N]; - Y2 = new double[N]; - Ydelta = new double[N]; - } - MPI_Bcast(X, N, MPI_DOUBLE, 0, world); - MPI_Bcast(Xs, N, MPI_DOUBLE, 0, world); - MPI_Bcast(Y, N, MPI_DOUBLE, 0, world); - MPI_Bcast(Y2, N, MPI_DOUBLE, 0, world); - MPI_Bcast(Ydelta, N, MPI_DOUBLE, 0, world); + MPI_Bcast(&N, 1, MPI_INT, 0, world); + MPI_Bcast(&deriv0, 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&derivN, 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&xmin, 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&xmax, 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&xmax_shifted, 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&isGridSpline, 1, MPI_INT, 0, world); + MPI_Bcast(&h, 1, MPI_DOUBLE, 0, world); + MPI_Bcast(&hsq, 1, MPI_DOUBLE, 0, world); + if(me != 0) { + X = new double[N]; + Xs = new double[N]; + Y = new double[N]; + Y2 = new double[N]; + Ydelta = new double[N]; + } + MPI_Bcast(X, N, MPI_DOUBLE, 0, world); + MPI_Bcast(Xs, N, MPI_DOUBLE, 0, world); + MPI_Bcast(Y, N, MPI_DOUBLE, 0, world); + MPI_Bcast(Y2, N, MPI_DOUBLE, 0, world); + MPI_Bcast(Ydelta, N, MPI_DOUBLE, 0, world); } /// Writes a Gnuplot script that plots the spline function. @@ -855,24 +857,24 @@ void PairMEAMSpline::SplineFunction::communicate(MPI_Comm& world, int me) /// This function is for debugging only! void PairMEAMSpline::SplineFunction::writeGnuplot(const char* filename, const char* title) const { - FILE* fp = fopen(filename, "w"); - fprintf(fp, "#!/usr/bin/env gnuplot\n"); - if(title) fprintf(fp, "set title \"%s\"\n", title); - double tmin = X[0] - (X[N-1] - X[0]) * 0.05; - double tmax = X[N-1] + (X[N-1] - X[0]) * 0.05; - double delta = (tmax - tmin) / (N*200); - fprintf(fp, "set xrange [%f:%f]\n", tmin, tmax); - fprintf(fp, "plot '-' with lines notitle, '-' with points notitle pt 3 lc 3\n"); - for(double x = tmin; x <= tmax+1e-8; x += delta) { - double y = eval(x); - fprintf(fp, "%f %f\n", x, y); - } - fprintf(fp, "e\n"); - for(int i = 0; i < N; i++) { - fprintf(fp, "%f %f\n", X[i], Y[i]); - } - fprintf(fp, "e\n"); - fclose(fp); + FILE* fp = fopen(filename, "w"); + fprintf(fp, "#!/usr/bin/env gnuplot\n"); + if(title) fprintf(fp, "set title \"%s\"\n", title); + double tmin = X[0] - (X[N-1] - X[0]) * 0.05; + double tmax = X[N-1] + (X[N-1] - X[0]) * 0.05; + double delta = (tmax - tmin) / (N*200); + fprintf(fp, "set xrange [%f:%f]\n", tmin, tmax); + fprintf(fp, "plot '-' with lines notitle, '-' with points notitle pt 3 lc 3\n"); + for(double x = tmin; x <= tmax+1e-8; x += delta) { + double y = eval(x); + fprintf(fp, "%f %f\n", x, y); + } + fprintf(fp, "e\n"); + for(int i = 0; i < N; i++) { + fprintf(fp, "%f %f\n", X[i], Y[i]); + } + fprintf(fp, "e\n"); + fclose(fp); } /* ---------------------------------------------------------------------- diff --git a/src/USER-MISC/pair_meam_spline.h b/src/USER-MISC/pair_meam_spline.h index 3d09cce23b..7e4f421909 100644 --- a/src/USER-MISC/pair_meam_spline.h +++ b/src/USER-MISC/pair_meam_spline.h @@ -38,217 +38,214 @@ namespace LAMMPS_NS { class PairMEAMSpline : public Pair { public: - PairMEAMSpline(class LAMMPS *); - virtual ~PairMEAMSpline(); - virtual void compute(int, int); - void settings(int, char **); - void coeff(int, char **); - void get_coeff(double *, double *); - double pair_density(int ); - double three_body_density(int ); - void init_style(); - void init_list(int, class NeighList *); - double init_one(int, int); - - // helper functions for compute() - - double compute_three_body_contrib_to_charge_density(int i, int& numBonds); // returns rho_value and returns numBonds by reference - double compute_embedding_energy_and_deriv(int eflag, int i, double rho_value); // returns the derivative of the embedding energy Uprime_i - void compute_three_body_contrib_to_forces(int i, int numBonds, double Uprime_i); - void compute_two_body_pair_interactions(); - - int ij_to_potl(int i, int j); - int i_to_potl(int i); - - - int pack_forward_comm(int, int *, double *, int, int *); - void unpack_forward_comm(int, int, double *); - int pack_reverse_comm(int, int, double *); - void unpack_reverse_comm(int, int *, double *); - double memory_usage(); - + PairMEAMSpline(class LAMMPS *); + virtual ~PairMEAMSpline(); + virtual void compute(int, int); + void settings(int, char **); + void coeff(int, char **); + void get_coeff(double *, double *); + double pair_density(int ); + double three_body_density(int ); + void init_style(); + void init_list(int, class NeighList *); + double init_one(int, int); + + // helper functions for compute() + + double compute_three_body_contrib_to_charge_density(int i, int& numBonds); // returns rho_value and returns numBonds by reference + double compute_embedding_energy_and_deriv(int eflag, int i, double rho_value); // returns the derivative of the embedding energy Uprime_i + void compute_three_body_contrib_to_forces(int i, int numBonds, double Uprime_i); + void compute_two_body_pair_interactions(); + + int ij_to_potl(int i, int j); + int i_to_potl(int i); + + int pack_forward_comm(int, int *, double *, int, int *); + void unpack_forward_comm(int, int, double *); + int pack_reverse_comm(int, int, double *); + void unpack_reverse_comm(int, int *, double *); + double memory_usage(); + protected: char **elements; // names of unique elements int *map; // mapping from atom types to elements int nelements; // # of unique elements - class SplineFunction { - public: - - /// Default constructor. - SplineFunction() : X(NULL), Xs(NULL), Y(NULL), Y2(NULL), Ydelta(NULL), N(0) {} - - /// Destructor. - ~SplineFunction() { - delete[] X; - delete[] Xs; - delete[] Y; - delete[] Y2; - delete[] Ydelta; - } - - /// Initialization of spline function. - void init(int _N, double _deriv0, double _derivN) { - N = _N; - deriv0 = _deriv0; - derivN = _derivN; - // if (X) delete[] X; - // if (Xs) delete[] Xs; - // if (Y) delete[] Y; - // if (Y2) delete[] Y2; - // if (Ydelta) delete[] Ydelta; - X = new double[N]; - Xs = new double[N]; - Y = new double[N]; - Y2 = new double[N]; - Ydelta = new double[N]; - } - - /// Adds a knot to the spline. - void setKnot(int n, double x, double y) { X[n] = x; Y[n] = y; } - - /// Returns the number of knots. - int numKnots() const { return N; } - - /// Parses the spline knots from a text file. - void parse(FILE* fp, Error* error, bool isNewFormat); - - /// Calculates the second derivatives of the cubic spline. - void prepareSpline(Error* error); - - /// Evaluates the spline function at position x. - inline double eval(double x) const - { - x -= xmin; - if(x <= 0.0) { // Left extrapolation. - return Y[0] + deriv0 * x; - } - else if(x >= xmax_shifted) { // Right extrapolation. - return Y[N-1] + derivN * (x - xmax_shifted); - } - else { -#if SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES - // Do interval search. - int klo = 0; - int khi = N-1; - while(khi - klo > 1) { - int k = (khi + klo) / 2; - if(Xs[k] > x) khi = k; - else klo = k; - } - double h = Xs[khi] - Xs[klo]; - // Do spline interpolation. - double a = (Xs[khi] - x)/h; - double b = 1.0 - a; // = (x - X[klo])/h - return a * Y[klo] + b * Y[khi] + ((a*a*a - a) * Y2[klo] + (b*b*b - b) * Y2[khi])*(h*h)/6.0; -#else - // For a spline with grid points, we can directly calculate the interval X is in. - int klo = (int)(x / h); - int khi = klo + 1; - double a = Xs[khi] - x; - double b = h - a; - return Y[khi] - a * Ydelta[klo] + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); -#endif - } - } - - /// Evaluates the spline function and its first derivative at position x. - inline double eval(double x, double& deriv) const - { - x -= xmin; - if(x <= 0.0) { // Left extrapolation. - deriv = deriv0; - return Y[0] + deriv0 * x; - } - else if(x >= xmax_shifted) { // Right extrapolation. - deriv = derivN; - return Y[N-1] + derivN * (x - xmax_shifted); - } - else { -#if SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES - // Do interval search. - int klo = 0; - int khi = N-1; - while(khi - klo > 1) { - int k = (khi + klo) / 2; - if(Xs[k] > x) khi = k; - else klo = k; - } - double h = Xs[khi] - Xs[klo]; - // Do spline interpolation. - double a = (Xs[khi] - x)/h; - double b = 1.0 - a; // = (x - X[klo])/h - deriv = (Y[khi] - Y[klo]) / h + ((3.0*b*b - 1.0) * Y2[khi] - (3.0*a*a - 1.0) * Y2[klo]) * h / 6.0; - return a * Y[klo] + b * Y[khi] + ((a*a*a - a) * Y2[klo] + (b*b*b - b) * Y2[khi]) * (h*h) / 6.0; -#else - // For a spline with grid points, we can directly calculate the interval X is in. - int klo = (int)(x / h); - int khi = klo + 1; - double a = Xs[khi] - x; - double b = h - a; - deriv = Ydelta[klo] + ((3.0*b*b - hsq) * Y2[khi] - (3.0*a*a - hsq) * Y2[klo]); - return Y[khi] - a * Ydelta[klo] + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); -#endif - } - } - - /// Returns the number of bytes used by this function object. - double memory_usage() const { return sizeof(*this) + sizeof(X[0]) * N * 3; } - - /// Returns the cutoff radius of this function. - double cutoff() const { return X[N-1]; } - - /// Writes a Gnuplot script that plots the spline function. - void writeGnuplot(const char* filename, const char* title = NULL) const; - - /// Broadcasts the spline function parameters to all processors. - void communicate(MPI_Comm& world, int me); - - private: - double* X; // Positions of spline knots - double* Xs; // Shifted positions of spline knots - double* Y; // Function values at spline knots - double* Y2; // Second derivatives at spline knots - double* Ydelta; // If this is a grid spline, Ydelta[i] = (Y[i+1]-Y[i])/h - int N; // Number of spline knots - double deriv0; // First derivative at knot 0 - double derivN; // First derivative at knot (N-1) - double xmin; // The beginning of the interval on which the spline function is defined. - double xmax; // The end of the interval on which the spline function is defined. - int isGridSpline; // Indicates that all spline knots are on a regular grid. - double h; // The distance between knots if this is a grid spline with equidistant knots. - double hsq; // The squared distance between knots if this is a grid spline with equidistant knots. - double xmax_shifted; // The end of the spline interval after it has been shifted to begin at X=0. - }; - - /// Helper data structure for potential routine. - struct MEAM2Body { - int tag; // holds the index of the second atom (j) - double r; - double f, fprime; - double del[3]; - }; - - SplineFunction* phis; // Phi_i(r_ij) - SplineFunction* rhos; // Rho_ij(r_ij) - SplineFunction* fs; // f_i(r_ij) - SplineFunction* Us; // U_i(rho) - SplineFunction* gs; // g_ij(cos_theta) - double* zero_atom_energies; // Shift embedding energy by this value to make it zero for a single atom in vacuum. - - double cutoff; // The cutoff radius - - double* Uprime_values; // Used for temporary storage of U'(rho) values - int nmax; // Size of temporary array. - int maxNeighbors; // The last maximum number of neighbors a single atoms has. - MEAM2Body* twoBodyInfo; // Temporary array. - - void read_file(const char* filename); - void allocate(); - + class SplineFunction { + public: + /// Default constructor. + SplineFunction() : X(NULL), Xs(NULL), Y(NULL), Y2(NULL), Ydelta(NULL), N(0) {} -}; + /// Destructor. + ~SplineFunction() { + delete[] X; + delete[] Xs; + delete[] Y; + delete[] Y2; + delete[] Ydelta; + } + + /// Initialization of spline function. + void init(int _N, double _deriv0, double _derivN) { + N = _N; + deriv0 = _deriv0; + derivN = _derivN; + // if (X) delete[] X; + // if (Xs) delete[] Xs; + // if (Y) delete[] Y; + // if (Y2) delete[] Y2; + // if (Ydelta) delete[] Ydelta; + X = new double[N]; + Xs = new double[N]; + Y = new double[N]; + Y2 = new double[N]; + Ydelta = new double[N]; + } + + /// Adds a knot to the spline. + void setKnot(int n, double x, double y) { X[n] = x; Y[n] = y; } + + /// Returns the number of knots. + int numKnots() const { return N; } + + /// Parses the spline knots from a text file. + void parse(FILE* fp, Error* error, bool isNewFormat); + + /// Calculates the second derivatives of the cubic spline. + void prepareSpline(Error* error); + + /// Evaluates the spline function at position x. + inline double eval(double x) const + { + x -= xmin; + if(x <= 0.0) { // Left extrapolation. + return Y[0] + deriv0 * x; + } + else if(x >= xmax_shifted) { // Right extrapolation. + return Y[N-1] + derivN * (x - xmax_shifted); + } + else { +#if SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES + // Do interval search. + int klo = 0; + int khi = N-1; + while(khi - klo > 1) { + int k = (khi + klo) / 2; + if(Xs[k] > x) khi = k; + else klo = k; + } + double h = Xs[khi] - Xs[klo]; + // Do spline interpolation. + double a = (Xs[khi] - x)/h; + double b = 1.0 - a; // = (x - X[klo])/h + return a * Y[klo] + b * Y[khi] + ((a*a*a - a) * Y2[klo] + (b*b*b - b) * Y2[khi])*(h*h)/6.0; +#else + // For a spline with grid points, we can directly calculate the interval X is in. + int klo = (int)(x / h); + int khi = klo + 1; + double a = Xs[khi] - x; + double b = h - a; + return Y[khi] - a * Ydelta[klo] + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); +#endif + } + } + + /// Evaluates the spline function and its first derivative at position x. + inline double eval(double x, double& deriv) const + { + x -= xmin; + if(x <= 0.0) { // Left extrapolation. + deriv = deriv0; + return Y[0] + deriv0 * x; + } + else if(x >= xmax_shifted) { // Right extrapolation. + deriv = derivN; + return Y[N-1] + derivN * (x - xmax_shifted); + } + else { +#if SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES + // Do interval search. + int klo = 0; + int khi = N-1; + while(khi - klo > 1) { + int k = (khi + klo) / 2; + if(Xs[k] > x) khi = k; + else klo = k; + } + double h = Xs[khi] - Xs[klo]; + // Do spline interpolation. + double a = (Xs[khi] - x)/h; + double b = 1.0 - a; // = (x - X[klo])/h + deriv = (Y[khi] - Y[klo]) / h + ((3.0*b*b - 1.0) * Y2[khi] - (3.0*a*a - 1.0) * Y2[klo]) * h / 6.0; + return a * Y[klo] + b * Y[khi] + ((a*a*a - a) * Y2[klo] + (b*b*b - b) * Y2[khi]) * (h*h) / 6.0; +#else + // For a spline with grid points, we can directly calculate the interval X is in. + int klo = (int)(x / h); + int khi = klo + 1; + double a = Xs[khi] - x; + double b = h - a; + deriv = Ydelta[klo] + ((3.0*b*b - hsq) * Y2[khi] - (3.0*a*a - hsq) * Y2[klo]); + return Y[khi] - a * Ydelta[klo] + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); +#endif + } + } + + /// Returns the number of bytes used by this function object. + double memory_usage() const { return sizeof(*this) + sizeof(X[0]) * N * 3; } + /// Returns the cutoff radius of this function. + double cutoff() const { return X[N-1]; } + + /// Writes a Gnuplot script that plots the spline function. + void writeGnuplot(const char* filename, const char* title = NULL) const; + + /// Broadcasts the spline function parameters to all processors. + void communicate(MPI_Comm& world, int me); + + private: + double* X; // Positions of spline knots + double* Xs; // Shifted positions of spline knots + double* Y; // Function values at spline knots + double* Y2; // Second derivatives at spline knots + double* Ydelta; // If this is a grid spline, Ydelta[i] = (Y[i+1]-Y[i])/h + int N; // Number of spline knots + double deriv0; // First derivative at knot 0 + double derivN; // First derivative at knot (N-1) + double xmin; // The beginning of the interval on which the spline function is defined. + double xmax; // The end of the interval on which the spline function is defined. + int isGridSpline; // Indicates that all spline knots are on a regular grid. + double h; // The distance between knots if this is a grid spline with equidistant knots. + double hsq; // The squared distance between knots if this is a grid spline with equidistant knots. + double xmax_shifted; // The end of the spline interval after it has been shifted to begin at X=0. + }; + + /// Helper data structure for potential routine. + struct MEAM2Body { + int tag; // holds the index of the second atom (j) + double r; + double f, fprime; + double del[3]; + }; + + SplineFunction* phis; // Phi_i(r_ij) + SplineFunction* rhos; // Rho_ij(r_ij) + SplineFunction* fs; // f_i(r_ij) + SplineFunction* Us; // U_i(rho) + SplineFunction* gs; // g_ij(cos_theta) + double* zero_atom_energies; // Shift embedding energy by this value to make it zero for a single atom in vacuum. + + double cutoff; // The cutoff radius + + double* Uprime_values; // Used for temporary storage of U'(rho) values + int nmax; // Size of temporary array. + int maxNeighbors; // The last maximum number of neighbors a single atoms has. + MEAM2Body* twoBodyInfo; // Temporary array. + + void read_file(const char* filename); + void allocate(); + +}; + } #endif From 7409c6d781325bcf334d8490d66f9a964ea52e1f Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Wed, 3 May 2017 16:56:07 -0500 Subject: [PATCH 13/26] Cleaned up atom->x and atom->f deferences. --- src/USER-MISC/pair_meam_spline.cpp | 71 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 59fcd2c889..17d893a502 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -170,14 +170,15 @@ double PairMEAMSpline::pair_density(int i) { double rho_value = 0; MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - + double** const x = atom->x; + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { int j = listfull->firstneigh[i][jj]; j &= NEIGHMASK; - double jdelx = atom->x[j][0] - atom->x[i][0]; - double jdely = atom->x[j][1] - atom->x[i][1]; - double jdelz = atom->x[j][2] - atom->x[i][2]; + double jdelx = x[j][0] - x[i][0]; + double jdely = x[j][1] - x[i][1]; + double jdelz = x[j][2] - x[i][2]; double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; double rij = sqrt(rij_sq); @@ -196,6 +197,7 @@ double PairMEAMSpline::three_body_density(int i) { double rho_value = 0; int numBonds=0; + double** const x = atom->x; MEAM2Body* nextTwoBodyInfo = twoBodyInfo; @@ -203,9 +205,9 @@ double PairMEAMSpline::three_body_density(int i) int j = listfull->firstneigh[i][jj]; j &= NEIGHMASK; - double jdelx = atom->x[j][0] - atom->x[i][0]; - double jdely = atom->x[j][1] - atom->x[i][1]; - double jdelz = atom->x[j][2] - atom->x[i][2]; + double jdelx = x[j][0] - x[i][0]; + double jdely = x[j][1] - x[i][1]; + double jdelz = x[j][2] - x[i][2]; double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; if(rij_sq < cutoff*cutoff) { @@ -239,14 +241,15 @@ double PairMEAMSpline::three_body_density(int i) double PairMEAMSpline::compute_three_body_contrib_to_charge_density(int i, int& numBonds) { double rho_value = 0; MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - + double** const x = atom->x; + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { int j = listfull->firstneigh[i][jj]; j &= NEIGHMASK; - double jdelx = atom->x[j][0] - atom->x[i][0]; - double jdely = atom->x[j][1] - atom->x[i][1]; - double jdelz = atom->x[j][2] - atom->x[i][2]; + double jdelx = x[j][0] - x[i][0]; + double jdely = x[j][1] - x[i][1]; + double jdelz = x[j][2] - x[i][2]; double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; if(rij_sq < cutoff*cutoff) { @@ -296,6 +299,7 @@ double PairMEAMSpline::compute_embedding_energy_and_deriv(int eflag, int i, doub void PairMEAMSpline::compute_three_body_contrib_to_forces(int i, int numBonds, double Uprime_i) { double forces_i[3] = {0, 0, 0}; + double** forces = atom->f; for(int jj = 0; jj < numBonds; jj++) { const MEAM2Body bondj = twoBodyInfo[jj]; @@ -345,9 +349,9 @@ void PairMEAMSpline::compute_three_body_contrib_to_forces(int i, int numBonds, d forces_i[2] -= fk[2]; int k = bondk->tag; - atom->f[k][0] += fk[0]; - atom->f[k][1] += fk[1]; - atom->f[k][2] += fk[2]; + forces[k][0] += fk[0]; + forces[k][1] += fk[1]; + forces[k][2] += fk[2]; if(evflag) { double delta_ij[3]; @@ -362,20 +366,23 @@ void PairMEAMSpline::compute_three_body_contrib_to_forces(int i, int numBonds, d } } - atom->f[i][0] -= forces_j[0]; - atom->f[i][1] -= forces_j[1]; - atom->f[i][2] -= forces_j[2]; - atom->f[j][0] += forces_j[0]; - atom->f[j][1] += forces_j[1]; - atom->f[j][2] += forces_j[2]; + forces[i][0] -= forces_j[0]; + forces[i][1] -= forces_j[1]; + forces[i][2] -= forces_j[2]; + forces[j][0] += forces_j[0]; + forces[j][1] += forces_j[1]; + forces[j][2] += forces_j[2]; } - atom->f[i][0] += forces_i[0]; - atom->f[i][1] += forces_i[1]; - atom->f[i][2] += forces_i[2]; + forces[i][0] += forces_i[0]; + forces[i][1] += forces_i[1]; + forces[i][2] += forces_i[2]; } void PairMEAMSpline::compute_two_body_pair_interactions() { + double** const x = atom->x; + double** forces = atom->f; + for(int ii = 0; ii < listhalf->inum; ii++) { int i = listhalf->ilist[ii]; @@ -384,9 +391,9 @@ void PairMEAMSpline::compute_two_body_pair_interactions() { j &= NEIGHMASK; double jdel[3]; - jdel[0] = atom->x[j][0] - atom->x[i][0]; - jdel[1] = atom->x[j][1] - atom->x[i][1]; - jdel[2] = atom->x[j][2] - atom->x[i][2]; + jdel[0] = x[j][0] - x[i][0]; + jdel[1] = x[j][1] - x[i][1]; + jdel[2] = x[j][2] - x[i][2]; double rij_sq = jdel[0]*jdel[0] + jdel[1]*jdel[1] + jdel[2]*jdel[2]; if(rij_sq < cutoff*cutoff) { @@ -405,12 +412,12 @@ void PairMEAMSpline::compute_two_body_pair_interactions() { fpair /= rij; - atom->f[i][0] += jdel[0]*fpair; - atom->f[i][1] += jdel[1]*fpair; - atom->f[i][2] += jdel[2]*fpair; - atom->f[j][0] -= jdel[0]*fpair; - atom->f[j][1] -= jdel[1]*fpair; - atom->f[j][2] -= jdel[2]*fpair; + forces[i][0] += jdel[0]*fpair; + forces[i][1] += jdel[1]*fpair; + forces[i][2] += jdel[2]*fpair; + forces[j][0] -= jdel[0]*fpair; + forces[j][1] -= jdel[1]*fpair; + forces[j][2] -= jdel[2]*fpair; if (evflag) ev_tally(i, j, atom->nlocal, force->newton_pair, pair_pot, 0.0, -fpair, jdel[0], jdel[1], jdel[2]); } From 45187a0fc77e483f807f518825e657f29ef34cd2 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 11:05:50 -0500 Subject: [PATCH 14/26] Fix system header #include style. --- src/USER-MISC/pair_meam_spline.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 17d893a502..1ad732609a 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -31,10 +31,10 @@ conform with pairing ------------------------------------------------------------------------- */ -#include "math.h" -#include "stdio.h" -#include "stdlib.h" -#include "string.h" +#include +#include +#include +#include #include "pair_meam_spline.h" #include "atom.h" #include "force.h" From 480727815a895a54c6f2ade5cb3d04f98fab007e Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 11:27:55 -0500 Subject: [PATCH 15/26] Starting to refactor in preparation to contruct OMP version. --- src/USER-MISC/pair_meam_spline.cpp | 180 ++++++++++++++++++++++++++++- 1 file changed, 174 insertions(+), 6 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 1ad732609a..704e76ee61 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -28,7 +28,7 @@ * 24-Sep-11 - AS: Adapted code to new interface of Error::one() function. * 20-Jun-13 - WT: Added support for multiple species types * 25-Apr-17 - DRT/PZ: Modified format of multiple species type to - conform with pairing + conform with pairing, updated to LAMMPS style ------------------------------------------------------------------------- */ #include @@ -102,6 +102,9 @@ PairMEAMSpline::~PairMEAMSpline() void PairMEAMSpline::compute(int eflag, int vflag) { + double** const x = atom->x; + double** forces = atom->f; + if (eflag || vflag) { ev_setup(eflag, vflag); } else { @@ -143,15 +146,140 @@ void PairMEAMSpline::compute(int eflag, int vflag) // compute charge density and numBonds - double rho_value = compute_three_body_contrib_to_charge_density(i, numBonds); + // double rho_value = compute_three_body_contrib_to_charge_density(i, numBonds); + MEAM2Body* nextTwoBodyInfo = twoBodyInfo; + double rho_value = 0; + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { + int j = listfull->firstneigh[i][jj]; + j &= NEIGHMASK; + + double jdelx = x[j][0] - x[i][0]; + double jdely = x[j][1] - x[i][1]; + double jdelz = x[j][2] - x[i][2]; + double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; + + if(rij_sq < cutoff*cutoff) { + double rij = sqrt(rij_sq); + double partial_sum = 0; + + nextTwoBodyInfo->tag = j; + nextTwoBodyInfo->r = rij; + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->del[0] = jdelx / rij; + nextTwoBodyInfo->del[1] = jdely / rij; + nextTwoBodyInfo->del[2] = jdelz / rij; + + for(int kk = 0; kk < numBonds; kk++) { + const MEAM2Body& bondk = twoBodyInfo[kk]; + double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + + nextTwoBodyInfo->del[1]*bondk.del[1] + + nextTwoBodyInfo->del[2]*bondk.del[2]); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); + } + + rho_value += nextTwoBodyInfo->f * partial_sum; + rho_value += rhos[i_to_potl(j)].eval(rij); + + numBonds++; + nextTwoBodyInfo++; + } + } // Compute embedding energy and its derivative - double Uprime_i = compute_embedding_energy_and_deriv(eflag, i, rho_value); + // double Uprime_i = compute_embedding_energy_and_deriv(eflag, i, rho_value); + double Uprime_i; + double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) + - zero_atom_energies[i_to_potl(i)]; + + Uprime_values[i] = Uprime_i; + if(eflag) { + if(eflag_global) + eng_vdwl += embeddingEnergy; + if(eflag_atom) + eatom[i] += embeddingEnergy; + } + // Compute three-body contributions to force - compute_three_body_contrib_to_forces(i, numBonds, Uprime_i); - + // compute_three_body_contrib_to_forces(i, numBonds, Uprime_i); + double forces_i[3] = {0, 0, 0}; + for(int jj = 0; jj < numBonds; jj++) { + const MEAM2Body bondj = twoBodyInfo[jj]; + double rij = bondj.r; + int j = bondj.tag; + + double f_rij_prime = bondj.fprime; + double f_rij = bondj.f; + + double forces_j[3] = {0, 0, 0}; + + MEAM2Body const* bondk = twoBodyInfo; + for(int kk = 0; kk < jj; kk++, ++bondk) { + double rik = bondk->r; + + double cos_theta = (bondj.del[0]*bondk->del[0] + + bondj.del[1]*bondk->del[1] + + bondj.del[2]*bondk->del[2]); + double g_prime; + double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); + double f_rik_prime = bondk->fprime; + double f_rik = bondk->f; + + double fij = -Uprime_i * g_value * f_rik * f_rij_prime; + double fik = -Uprime_i * g_value * f_rij * f_rik_prime; + + double prefactor = Uprime_i * f_rij * f_rik * g_prime; + double prefactor_ij = prefactor / rij; + double prefactor_ik = prefactor / rik; + fij += prefactor_ij * cos_theta; + fik += prefactor_ik * cos_theta; + + double fj[3], fk[3]; + + fj[0] = bondj.del[0] * fij - bondk->del[0] * prefactor_ij; + fj[1] = bondj.del[1] * fij - bondk->del[1] * prefactor_ij; + fj[2] = bondj.del[2] * fij - bondk->del[2] * prefactor_ij; + forces_j[0] += fj[0]; + forces_j[1] += fj[1]; + forces_j[2] += fj[2]; + + fk[0] = bondk->del[0] * fik - bondj.del[0] * prefactor_ik; + fk[1] = bondk->del[1] * fik - bondj.del[1] * prefactor_ik; + fk[2] = bondk->del[2] * fik - bondj.del[2] * prefactor_ik; + forces_i[0] -= fk[0]; + forces_i[1] -= fk[1]; + forces_i[2] -= fk[2]; + + int k = bondk->tag; + forces[k][0] += fk[0]; + forces[k][1] += fk[1]; + forces[k][2] += fk[2]; + + if(evflag) { + double delta_ij[3]; + double delta_ik[3]; + delta_ij[0] = bondj.del[0] * rij; + delta_ij[1] = bondj.del[1] * rij; + delta_ij[2] = bondj.del[2] * rij; + delta_ik[0] = bondk->del[0] * rik; + delta_ik[1] = bondk->del[1] * rik; + delta_ik[2] = bondk->del[2] * rik; + ev_tally3(i, j, k, 0.0, 0.0, fj, fk, delta_ij, delta_ik); + } + } + + forces[i][0] -= forces_j[0]; + forces[i][1] -= forces_j[1]; + forces[i][2] -= forces_j[2]; + forces[j][0] += forces_j[0]; + forces[j][1] += forces_j[1]; + forces[j][2] += forces_j[2]; + } + + forces[i][0] += forces_i[0]; + forces[i][1] += forces_i[1]; + forces[i][2] += forces_i[2]; } // Communicate U'(rho) values @@ -159,7 +287,47 @@ void PairMEAMSpline::compute(int eflag, int vflag) comm->forward_comm_pair(this); // Compute two-body pair interactions - compute_two_body_pair_interactions(); + // compute_two_body_pair_interactions(); + for(int ii = 0; ii < listhalf->inum; ii++) { + int i = listhalf->ilist[ii]; + + for(int jj = 0; jj < listhalf->numneigh[i]; jj++) { + int j = listhalf->firstneigh[i][jj]; + j &= NEIGHMASK; + + double jdel[3]; + jdel[0] = x[j][0] - x[i][0]; + jdel[1] = x[j][1] - x[i][1]; + jdel[2] = x[j][2] - x[i][2]; + double rij_sq = jdel[0]*jdel[0] + jdel[1]*jdel[1] + jdel[2]*jdel[2]; + + if(rij_sq < cutoff*cutoff) { + double rij = sqrt(rij_sq); + + double rho_prime_i,rho_prime_j; + rhos[i_to_potl(i)].eval(rij,rho_prime_i); + rhos[i_to_potl(j)].eval(rij,rho_prime_j); + double fpair = rho_prime_j * Uprime_values[i] + rho_prime_i*Uprime_values[j]; + double pair_pot_deriv; + double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); + + fpair += pair_pot_deriv; + + // Divide by r_ij to get forces from gradient + + fpair /= rij; + + forces[i][0] += jdel[0]*fpair; + forces[i][1] += jdel[1]*fpair; + forces[i][2] += jdel[2]*fpair; + forces[j][0] -= jdel[0]*fpair; + forces[j][1] -= jdel[1]*fpair; + forces[j][2] -= jdel[2]*fpair; + if (evflag) ev_tally(i, j, atom->nlocal, force->newton_pair, + pair_pot, 0.0, -fpair, jdel[0], jdel[1], jdel[2]); + } + } + } if(vflag_fdotr) virial_fdotr_compute(); From 2f71245d827769f7d11afc0bae78b49890d6bac3 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 13:00:06 -0500 Subject: [PATCH 16/26] Removed extra "helper" functions. --- src/USER-MISC/pair_meam_spline.cpp | 187 ----------------------------- src/USER-MISC/pair_meam_spline.h | 5 - 2 files changed, 192 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 704e76ee61..5a96d1f9c6 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -406,193 +406,6 @@ double PairMEAMSpline::three_body_density(int i) return rho_value; } -double PairMEAMSpline::compute_three_body_contrib_to_charge_density(int i, int& numBonds) { - double rho_value = 0; - MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - double** const x = atom->x; - - for(int jj = 0; jj < listfull->numneigh[i]; jj++) { - int j = listfull->firstneigh[i][jj]; - j &= NEIGHMASK; - - double jdelx = x[j][0] - x[i][0]; - double jdely = x[j][1] - x[i][1]; - double jdelz = x[j][2] - x[i][2]; - double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - - if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - double partial_sum = 0; - - nextTwoBodyInfo->tag = j; - nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); - nextTwoBodyInfo->del[0] = jdelx / rij; - nextTwoBodyInfo->del[1] = jdely / rij; - nextTwoBodyInfo->del[2] = jdelz / rij; - - for(int kk = 0; kk < numBonds; kk++) { - const MEAM2Body& bondk = twoBodyInfo[kk]; - double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + - nextTwoBodyInfo->del[1]*bondk.del[1] + - nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); - } - - rho_value += nextTwoBodyInfo->f * partial_sum; - rho_value += rhos[i_to_potl(j)].eval(rij); - - numBonds++; - nextTwoBodyInfo++; - } - } - - return rho_value; -} - -double PairMEAMSpline::compute_embedding_energy_and_deriv(int eflag, int i, double rho_value) { - double Uprime_i; - double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) - - zero_atom_energies[i_to_potl(i)]; - - Uprime_values[i] = Uprime_i; - if(eflag) { - if(eflag_global) - eng_vdwl += embeddingEnergy; - if(eflag_atom) - eatom[i] += embeddingEnergy; - } - return Uprime_i; -} - -void PairMEAMSpline::compute_three_body_contrib_to_forces(int i, int numBonds, double Uprime_i) { - double forces_i[3] = {0, 0, 0}; - double** forces = atom->f; - - for(int jj = 0; jj < numBonds; jj++) { - const MEAM2Body bondj = twoBodyInfo[jj]; - double rij = bondj.r; - int j = bondj.tag; - - double f_rij_prime = bondj.fprime; - double f_rij = bondj.f; - - double forces_j[3] = {0, 0, 0}; - - MEAM2Body const* bondk = twoBodyInfo; - for(int kk = 0; kk < jj; kk++, ++bondk) { - double rik = bondk->r; - - double cos_theta = (bondj.del[0]*bondk->del[0] + - bondj.del[1]*bondk->del[1] + - bondj.del[2]*bondk->del[2]); - double g_prime; - double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); - double f_rik_prime = bondk->fprime; - double f_rik = bondk->f; - - double fij = -Uprime_i * g_value * f_rik * f_rij_prime; - double fik = -Uprime_i * g_value * f_rij * f_rik_prime; - - double prefactor = Uprime_i * f_rij * f_rik * g_prime; - double prefactor_ij = prefactor / rij; - double prefactor_ik = prefactor / rik; - fij += prefactor_ij * cos_theta; - fik += prefactor_ik * cos_theta; - - double fj[3], fk[3]; - - fj[0] = bondj.del[0] * fij - bondk->del[0] * prefactor_ij; - fj[1] = bondj.del[1] * fij - bondk->del[1] * prefactor_ij; - fj[2] = bondj.del[2] * fij - bondk->del[2] * prefactor_ij; - forces_j[0] += fj[0]; - forces_j[1] += fj[1]; - forces_j[2] += fj[2]; - - fk[0] = bondk->del[0] * fik - bondj.del[0] * prefactor_ik; - fk[1] = bondk->del[1] * fik - bondj.del[1] * prefactor_ik; - fk[2] = bondk->del[2] * fik - bondj.del[2] * prefactor_ik; - forces_i[0] -= fk[0]; - forces_i[1] -= fk[1]; - forces_i[2] -= fk[2]; - - int k = bondk->tag; - forces[k][0] += fk[0]; - forces[k][1] += fk[1]; - forces[k][2] += fk[2]; - - if(evflag) { - double delta_ij[3]; - double delta_ik[3]; - delta_ij[0] = bondj.del[0] * rij; - delta_ij[1] = bondj.del[1] * rij; - delta_ij[2] = bondj.del[2] * rij; - delta_ik[0] = bondk->del[0] * rik; - delta_ik[1] = bondk->del[1] * rik; - delta_ik[2] = bondk->del[2] * rik; - ev_tally3(i, j, k, 0.0, 0.0, fj, fk, delta_ij, delta_ik); - } - } - - forces[i][0] -= forces_j[0]; - forces[i][1] -= forces_j[1]; - forces[i][2] -= forces_j[2]; - forces[j][0] += forces_j[0]; - forces[j][1] += forces_j[1]; - forces[j][2] += forces_j[2]; - } - - forces[i][0] += forces_i[0]; - forces[i][1] += forces_i[1]; - forces[i][2] += forces_i[2]; -} - -void PairMEAMSpline::compute_two_body_pair_interactions() { - double** const x = atom->x; - double** forces = atom->f; - - for(int ii = 0; ii < listhalf->inum; ii++) { - int i = listhalf->ilist[ii]; - - for(int jj = 0; jj < listhalf->numneigh[i]; jj++) { - int j = listhalf->firstneigh[i][jj]; - j &= NEIGHMASK; - - double jdel[3]; - jdel[0] = x[j][0] - x[i][0]; - jdel[1] = x[j][1] - x[i][1]; - jdel[2] = x[j][2] - x[i][2]; - double rij_sq = jdel[0]*jdel[0] + jdel[1]*jdel[1] + jdel[2]*jdel[2]; - - if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - - double rho_prime_i,rho_prime_j; - rhos[i_to_potl(i)].eval(rij,rho_prime_i); - rhos[i_to_potl(j)].eval(rij,rho_prime_j); - double fpair = rho_prime_j * Uprime_values[i] + rho_prime_i*Uprime_values[j]; - double pair_pot_deriv; - double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); - - fpair += pair_pot_deriv; - - // Divide by r_ij to get forces from gradient - - fpair /= rij; - - forces[i][0] += jdel[0]*fpair; - forces[i][1] += jdel[1]*fpair; - forces[i][2] += jdel[2]*fpair; - forces[j][0] -= jdel[0]*fpair; - forces[j][1] -= jdel[1]*fpair; - forces[j][2] -= jdel[2]*fpair; - if (evflag) ev_tally(i, j, atom->nlocal, force->newton_pair, - pair_pot, 0.0, -fpair, jdel[0], jdel[1], jdel[2]); - } - } - } -} - /* ---------------------------------------------------------------------- helper functions to map atom types to potential array indices ------------------------------------------------------------------------- */ diff --git a/src/USER-MISC/pair_meam_spline.h b/src/USER-MISC/pair_meam_spline.h index 7e4f421909..4be8f81ede 100644 --- a/src/USER-MISC/pair_meam_spline.h +++ b/src/USER-MISC/pair_meam_spline.h @@ -52,11 +52,6 @@ public: // helper functions for compute() - double compute_three_body_contrib_to_charge_density(int i, int& numBonds); // returns rho_value and returns numBonds by reference - double compute_embedding_energy_and_deriv(int eflag, int i, double rho_value); // returns the derivative of the embedding energy Uprime_i - void compute_three_body_contrib_to_forces(int i, int numBonds, double Uprime_i); - void compute_two_body_pair_interactions(); - int ij_to_potl(int i, int j); int i_to_potl(int i); From 349c1443a1c023cca4e4885b53318ee2674ff044 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 13:01:45 -0500 Subject: [PATCH 17/26] Cleanup. --- src/USER-MISC/pair_meam_spline.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 5a96d1f9c6..9fcb6fed9c 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -186,8 +186,6 @@ void PairMEAMSpline::compute(int eflag, int vflag) } // Compute embedding energy and its derivative - - // double Uprime_i = compute_embedding_energy_and_deriv(eflag, i, rho_value); double Uprime_i; double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) - zero_atom_energies[i_to_potl(i)]; @@ -201,8 +199,6 @@ void PairMEAMSpline::compute(int eflag, int vflag) } // Compute three-body contributions to force - - // compute_three_body_contrib_to_forces(i, numBonds, Uprime_i); double forces_i[3] = {0, 0, 0}; for(int jj = 0; jj < numBonds; jj++) { const MEAM2Body bondj = twoBodyInfo[jj]; @@ -287,7 +283,6 @@ void PairMEAMSpline::compute(int eflag, int vflag) comm->forward_comm_pair(this); // Compute two-body pair interactions - // compute_two_body_pair_interactions(); for(int ii = 0; ii < listhalf->inum; ii++) { int i = listhalf->ilist[ii]; From 5accce976a13d7e104c270d8a9fad414a563106a Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 13:02:09 -0500 Subject: [PATCH 18/26] Cleanup. --- src/USER-MISC/pair_meam_spline.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 9fcb6fed9c..d86549912a 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -145,8 +145,6 @@ void PairMEAMSpline::compute(int eflag, int vflag) int numBonds = 0; // compute charge density and numBonds - - // double rho_value = compute_three_body_contrib_to_charge_density(i, numBonds); MEAM2Body* nextTwoBodyInfo = twoBodyInfo; double rho_value = 0; for(int jj = 0; jj < listfull->numneigh[i]; jj++) { From ffdc8b556d004fa4ee9b962aaf06e6627e7e73d8 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 13:03:09 -0500 Subject: [PATCH 19/26] Cleanup. --- src/USER-MISC/pair_meam_spline.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index d86549912a..d714652d61 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -458,9 +458,6 @@ void PairMEAMSpline::coeff(int narg, char **arg) { int i,j,n; - if (!allocated) - allocate(); - if (narg != 3 + atom->ntypes) error->all(FLERR,"Incorrect args for pair coefficients"); From 754b40cb310068fb2f391b8a535fb0a55bf8ec77 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 13:16:46 -0500 Subject: [PATCH 20/26] Removed unused functions. --- src/USER-MISC/pair_meam_spline.cpp | 72 ------------------------------ 1 file changed, 72 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index d714652d61..ff9cb80e4a 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -327,78 +327,6 @@ void PairMEAMSpline::compute(int eflag, int vflag) } -double PairMEAMSpline::pair_density(int i) -{ - double rho_value = 0; - MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - double** const x = atom->x; - - for(int jj = 0; jj < listfull->numneigh[i]; jj++) { - int j = listfull->firstneigh[i][jj]; - j &= NEIGHMASK; - - double jdelx = x[j][0] - x[i][0]; - double jdely = x[j][1] - x[i][1]; - double jdelz = x[j][2] - x[i][2]; - double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - double rij = sqrt(rij_sq); - - if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - rho_value += rhos[i_to_potl(j)].eval(rij); - } - } - - return rho_value; -} - - - -double PairMEAMSpline::three_body_density(int i) -{ - double rho_value = 0; - int numBonds=0; - double** const x = atom->x; - - MEAM2Body* nextTwoBodyInfo = twoBodyInfo; - - for(int jj = 0; jj < listfull->numneigh[i]; jj++) { - int j = listfull->firstneigh[i][jj]; - j &= NEIGHMASK; - - double jdelx = x[j][0] - x[i][0]; - double jdely = x[j][1] - x[i][1]; - double jdelz = x[j][2] - x[i][2]; - double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - - if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - double partial_sum = 0; - - nextTwoBodyInfo->tag = j; - nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); - nextTwoBodyInfo->del[0] = jdelx / rij; - nextTwoBodyInfo->del[1] = jdely / rij; - nextTwoBodyInfo->del[2] = jdelz / rij; - - for(int kk = 0; kk < numBonds; kk++) { - const MEAM2Body& bondk = twoBodyInfo[kk]; - double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + - nextTwoBodyInfo->del[1]*bondk.del[1] + - nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); - } - - rho_value += nextTwoBodyInfo->f * partial_sum; - numBonds++; - nextTwoBodyInfo++; - } - } - - return rho_value; -} - /* ---------------------------------------------------------------------- helper functions to map atom types to potential array indices ------------------------------------------------------------------------- */ From f7230006fef49bd57724f86b9b846fb3521b80d5 Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 15:08:04 -0500 Subject: [PATCH 21/26] OpenMP version added. --- src/USER-MISC/pair_meam_spline.cpp | 2 +- src/USER-OMP/pair_meam_spline_omp.cpp | 40 +++++++++++++++++++-------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index ff9cb80e4a..7417e2ce64 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -304,7 +304,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) double pair_pot_deriv; double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); - fpair += pair_pot_deriv; + fpair += pair_pot_deriv; // Divide by r_ij to get forces from gradient diff --git a/src/USER-OMP/pair_meam_spline_omp.cpp b/src/USER-OMP/pair_meam_spline_omp.cpp index 98e1541319..b4e0c48acc 100644 --- a/src/USER-OMP/pair_meam_spline_omp.cpp +++ b/src/USER-OMP/pair_meam_spline_omp.cpp @@ -140,19 +140,25 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) nextTwoBodyInfo->tag = j; nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = f.eval(rij, nextTwoBodyInfo->fprime); + // nextTwoBodyInfo->f = f.eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); nextTwoBodyInfo->del[0] = jdelx / rij; nextTwoBodyInfo->del[1] = jdely / rij; nextTwoBodyInfo->del[2] = jdelz / rij; for(int kk = 0; kk < numBonds; kk++) { const MEAM2Body& bondk = myTwoBodyInfo[kk]; - double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + nextTwoBodyInfo->del[1]*bondk.del[1] + nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * g.eval(cos_theta); + double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + + nextTwoBodyInfo->del[1]*bondk.del[1] + + nextTwoBodyInfo->del[2]*bondk.del[2]); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); + // double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + nextTwoBodyInfo->del[1]*bondk.del[1] + nextTwoBodyInfo->del[2]*bondk.del[2]); + // partial_sum += bondk.f * g.eval(cos_theta); } rho_value += nextTwoBodyInfo->f * partial_sum; - rho_value += rho.eval(rij); + // rho_value += rho.eval(rij); + rho_value += rhos[i_to_potl(j)].eval(rij); numBonds++; nextTwoBodyInfo++; @@ -161,7 +167,9 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) // Compute embedding energy and its derivative. double Uprime_i; - double embeddingEnergy = U.eval(rho_value, Uprime_i) - zero_atom_energy; + // double embeddingEnergy = U.eval(rho_value, Uprime_i) - zero_atom_energy; + double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) + - zero_atom_energies[i_to_potl(i)]; Uprime_thr[i] = Uprime_i; if (EFLAG) e_tally_thr(this,i,i,nlocal,1/*newton_pair*/,embeddingEnergy,0.0,thr); @@ -187,7 +195,8 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) + bondj.del[1]*bondk->del[1] + bondj.del[2]*bondk->del[2]); double g_prime; - double g_value = g.eval(cos_theta, g_prime); + // double g_value = g.eval(cos_theta, g_prime); + double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); const double f_rik_prime = bondk->fprime; const double f_rik = bondk->f; @@ -292,13 +301,20 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) if(rij_sq < cutforcesq) { double rij = sqrt(rij_sq); - double rho_prime; - rho.eval(rij, rho_prime); - double fpair = rho_prime * (Uprime_values[i] + Uprime_values[j]); - + // double rho_prime; + // rho.eval(rij, rho_prime); + // double fpair = rho_prime * (Uprime_values[i] + Uprime_values[j]); + double rho_prime_i,rho_prime_j; + rhos[i_to_potl(i)].eval(rij,rho_prime_i); + rhos[i_to_potl(j)].eval(rij,rho_prime_j); + double fpair = rho_prime_j * Uprime_values[i] + rho_prime_i*Uprime_values[j]; + + // double pair_pot_deriv; + // double pair_pot = phi.eval(rij, pair_pot_deriv); double pair_pot_deriv; - double pair_pot = phi.eval(rij, pair_pot_deriv); - fpair += pair_pot_deriv; + double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); + + fpair += pair_pot_deriv; // Divide by r_ij to get forces from gradient. fpair /= rij; From 42531389df270656829674afc53c51f4732f90eb Mon Sep 17 00:00:00 2001 From: DallasTrinkle Date: Thu, 4 May 2017 15:28:11 -0500 Subject: [PATCH 22/26] Cleanup of style (removing all tabs, shortened long lines). --- src/USER-MISC/pair_meam_spline.cpp | 197 +++++++++++++------------- src/USER-MISC/pair_meam_spline.h | 160 +++++++++++---------- src/USER-OMP/pair_meam_spline_omp.cpp | 29 ++-- 3 files changed, 194 insertions(+), 192 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 7417e2ce64..6fbff31753 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -14,8 +14,8 @@ /* ---------------------------------------------------------------------- Contributing author: Alexander Stukowski (LLNL), alex@stukowski.com Will Tipton (Cornell), wwt26@cornell.edu - Dallas R. Trinkle (UIUC), dtrinkle@illinois.edu - Pinchao Zhang (UIUC) + Dallas R. Trinkle (UIUC), dtrinkle@illinois.edu + Pinchao Zhang (UIUC) see LLNL copyright notice at bottom of file ------------------------------------------------------------------------- */ @@ -157,29 +157,29 @@ void PairMEAMSpline::compute(int eflag, int vflag) double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; if(rij_sq < cutoff*cutoff) { - double rij = sqrt(rij_sq); - double partial_sum = 0; - - nextTwoBodyInfo->tag = j; - nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); - nextTwoBodyInfo->del[0] = jdelx / rij; - nextTwoBodyInfo->del[1] = jdely / rij; - nextTwoBodyInfo->del[2] = jdelz / rij; - - for(int kk = 0; kk < numBonds; kk++) { - const MEAM2Body& bondk = twoBodyInfo[kk]; - double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + - nextTwoBodyInfo->del[1]*bondk.del[1] + - nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); - } - - rho_value += nextTwoBodyInfo->f * partial_sum; - rho_value += rhos[i_to_potl(j)].eval(rij); - - numBonds++; - nextTwoBodyInfo++; + double rij = sqrt(rij_sq); + double partial_sum = 0; + + nextTwoBodyInfo->tag = j; + nextTwoBodyInfo->r = rij; + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->del[0] = jdelx / rij; + nextTwoBodyInfo->del[1] = jdely / rij; + nextTwoBodyInfo->del[2] = jdelz / rij; + + for(int kk = 0; kk < numBonds; kk++) { + const MEAM2Body& bondk = twoBodyInfo[kk]; + double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + + nextTwoBodyInfo->del[1]*bondk.del[1] + + nextTwoBodyInfo->del[2]*bondk.del[2]); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); + } + + rho_value += nextTwoBodyInfo->f * partial_sum; + rho_value += rhos[i_to_potl(j)].eval(rij); + + numBonds++; + nextTwoBodyInfo++; } } @@ -191,9 +191,9 @@ void PairMEAMSpline::compute(int eflag, int vflag) Uprime_values[i] = Uprime_i; if(eflag) { if(eflag_global) - eng_vdwl += embeddingEnergy; + eng_vdwl += embeddingEnergy; if(eflag_atom) - eatom[i] += embeddingEnergy; + eatom[i] += embeddingEnergy; } // Compute three-body contributions to force @@ -210,57 +210,57 @@ void PairMEAMSpline::compute(int eflag, int vflag) MEAM2Body const* bondk = twoBodyInfo; for(int kk = 0; kk < jj; kk++, ++bondk) { - double rik = bondk->r; - - double cos_theta = (bondj.del[0]*bondk->del[0] + - bondj.del[1]*bondk->del[1] + - bondj.del[2]*bondk->del[2]); - double g_prime; - double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); - double f_rik_prime = bondk->fprime; - double f_rik = bondk->f; - - double fij = -Uprime_i * g_value * f_rik * f_rij_prime; - double fik = -Uprime_i * g_value * f_rij * f_rik_prime; - - double prefactor = Uprime_i * f_rij * f_rik * g_prime; - double prefactor_ij = prefactor / rij; - double prefactor_ik = prefactor / rik; - fij += prefactor_ij * cos_theta; - fik += prefactor_ik * cos_theta; - - double fj[3], fk[3]; - - fj[0] = bondj.del[0] * fij - bondk->del[0] * prefactor_ij; - fj[1] = bondj.del[1] * fij - bondk->del[1] * prefactor_ij; - fj[2] = bondj.del[2] * fij - bondk->del[2] * prefactor_ij; - forces_j[0] += fj[0]; - forces_j[1] += fj[1]; - forces_j[2] += fj[2]; - - fk[0] = bondk->del[0] * fik - bondj.del[0] * prefactor_ik; - fk[1] = bondk->del[1] * fik - bondj.del[1] * prefactor_ik; - fk[2] = bondk->del[2] * fik - bondj.del[2] * prefactor_ik; - forces_i[0] -= fk[0]; - forces_i[1] -= fk[1]; - forces_i[2] -= fk[2]; - - int k = bondk->tag; - forces[k][0] += fk[0]; - forces[k][1] += fk[1]; - forces[k][2] += fk[2]; - - if(evflag) { - double delta_ij[3]; - double delta_ik[3]; - delta_ij[0] = bondj.del[0] * rij; - delta_ij[1] = bondj.del[1] * rij; - delta_ij[2] = bondj.del[2] * rij; - delta_ik[0] = bondk->del[0] * rik; - delta_ik[1] = bondk->del[1] * rik; - delta_ik[2] = bondk->del[2] * rik; - ev_tally3(i, j, k, 0.0, 0.0, fj, fk, delta_ij, delta_ik); - } + double rik = bondk->r; + + double cos_theta = (bondj.del[0]*bondk->del[0] + + bondj.del[1]*bondk->del[1] + + bondj.del[2]*bondk->del[2]); + double g_prime; + double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); + double f_rik_prime = bondk->fprime; + double f_rik = bondk->f; + + double fij = -Uprime_i * g_value * f_rik * f_rij_prime; + double fik = -Uprime_i * g_value * f_rij * f_rik_prime; + + double prefactor = Uprime_i * f_rij * f_rik * g_prime; + double prefactor_ij = prefactor / rij; + double prefactor_ik = prefactor / rik; + fij += prefactor_ij * cos_theta; + fik += prefactor_ik * cos_theta; + + double fj[3], fk[3]; + + fj[0] = bondj.del[0] * fij - bondk->del[0] * prefactor_ij; + fj[1] = bondj.del[1] * fij - bondk->del[1] * prefactor_ij; + fj[2] = bondj.del[2] * fij - bondk->del[2] * prefactor_ij; + forces_j[0] += fj[0]; + forces_j[1] += fj[1]; + forces_j[2] += fj[2]; + + fk[0] = bondk->del[0] * fik - bondj.del[0] * prefactor_ik; + fk[1] = bondk->del[1] * fik - bondj.del[1] * prefactor_ik; + fk[2] = bondk->del[2] * fik - bondj.del[2] * prefactor_ik; + forces_i[0] -= fk[0]; + forces_i[1] -= fk[1]; + forces_i[2] -= fk[2]; + + int k = bondk->tag; + forces[k][0] += fk[0]; + forces[k][1] += fk[1]; + forces[k][2] += fk[2]; + + if(evflag) { + double delta_ij[3]; + double delta_ik[3]; + delta_ij[0] = bondj.del[0] * rij; + delta_ij[1] = bondj.del[1] * rij; + delta_ij[2] = bondj.del[2] * rij; + delta_ik[0] = bondk->del[0] * rik; + delta_ik[1] = bondk->del[1] * rik; + delta_ik[2] = bondk->del[2] * rik; + ev_tally3(i, j, k, 0.0, 0.0, fj, fk, delta_ij, delta_ik); + } } forces[i][0] -= forces_j[0]; @@ -304,7 +304,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) double pair_pot_deriv; double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); - fpair += pair_pot_deriv; + fpair += pair_pot_deriv; // Divide by r_ij to get forces from gradient @@ -406,18 +406,18 @@ void PairMEAMSpline::coeff(int narg, char **arg) // old style: we only have one species, so we're either "NULL" or we match. for (i = 3; i < narg; i++) if (strcmp(arg[i],"NULL") == 0) - map[i-2] = -1; + map[i-2] = -1; else - map[i-2] = 0; + map[i-2] = 0; } else { for (i = 3; i < narg; i++) { if (strcmp(arg[i],"NULL") == 0) { - map[i-2] = -1; - continue; + map[i-2] = -1; + continue; } for (j = 0; j < nelements; j++) - if (strcmp(arg[i],elements[j]) == 0) - break; + if (strcmp(arg[i],elements[j]) == 0) + break; if (j < nelements) map[i-2] = j; else error->all(FLERR,"No matching element in EAM potential file"); } @@ -460,7 +460,7 @@ void PairMEAMSpline::read_file(const char* filename) char line[MAXLINE]; fgets(line, MAXLINE, fp); - // Second line holds potential type (currently just "meam/spline") in new potential format. + // Second line holds potential type ("meam/spline") in new potential format. bool isNewFormat; long loc = ftell(fp); fgets(line, MAXLINE, fp); @@ -471,22 +471,22 @@ void PairMEAMSpline::read_file(const char* filename) const char *sep = " ,;:-\t\n"; // overkill, but safe word = strsep(&linep, sep); if (! *word) - error->one(FLERR, "Need to include number of atomic species on meam/spline line in potential file"); + error->one(FLERR, "Need to include number of atomic species on meam/spline line in potential file"); int n = atoi(word); if (n<1) - error->one(FLERR, "Invalid number of atomic species on meam/spline line in potential file"); + error->one(FLERR, "Invalid number of atomic species on meam/spline line in potential file"); nelements = n; elements = new char*[n]; for (int i=0; ione(FLERR, "Not enough atomic species in meam/spline\n"); - elements[i] = new char[strlen(word)+1]; - strcpy(elements[i], word); + word = strsep(&linep, sep); + if (! *word) + error->one(FLERR, "Not enough atomic species in meam/spline\n"); + elements[i] = new char[strlen(word)+1]; + strcpy(elements[i], word); } } else { isNewFormat = false; - nelements = 1; // old format only handles one species anyway; this is for backwards compatibility + nelements = 1; // old format only handles one species; (backwards compatibility) elements = new char*[1]; elements[0] = new char[1]; strcpy(elements[0], ""); @@ -607,7 +607,8 @@ double PairMEAMSpline::init_one(int i, int j) /* ---------------------------------------------------------------------- */ -int PairMEAMSpline::pack_forward_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) +int PairMEAMSpline::pack_forward_comm(int n, int *list, double *buf, + int pbc_flag, int *pbc) { int* list_iter = list; int* list_iter_end = list + n; @@ -646,7 +647,8 @@ double PairMEAMSpline::memory_usage() /// Parses the spline knots from a text file. -void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error, bool isNewFormat) +void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error, + bool isNewFormat) { char line[MAXLINE]; @@ -761,7 +763,8 @@ void PairMEAMSpline::SplineFunction::communicate(MPI_Comm& world, int me) /// Writes a Gnuplot script that plots the spline function. /// /// This function is for debugging only! -void PairMEAMSpline::SplineFunction::writeGnuplot(const char* filename, const char* title) const +void PairMEAMSpline::SplineFunction::writeGnuplot(const char* filename, + const char* title) const { FILE* fp = fopen(filename, "w"); fprintf(fp, "#!/usr/bin/env gnuplot\n"); diff --git a/src/USER-MISC/pair_meam_spline.h b/src/USER-MISC/pair_meam_spline.h index 4be8f81ede..31f64cc3e5 100644 --- a/src/USER-MISC/pair_meam_spline.h +++ b/src/USER-MISC/pair_meam_spline.h @@ -28,10 +28,12 @@ PairStyle(meam/spline,PairMEAMSpline) namespace LAMMPS_NS { -/// Set this to 1 if you intend to use MEAM potentials with non-uniform spline knots. -/// Set this to 0 if you intend to use only MEAM potentials with spline knots on a uniform grid. -/// -/// With SUPPORT_NON_GRID_SPLINES == 0, the code runs about 50% faster. +// Set this to 1 if you intend to use MEAM potentials with +// non-uniform spline knots. +// Set this to 0 if you intend to use only MEAM potentials with +// spline knots on a uniform grid. +// +// With SUPPORT_NON_GRID_SPLINES == 0, the code runs about 50% faster. #define SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES 0 @@ -114,33 +116,35 @@ protected: { x -= xmin; if(x <= 0.0) { // Left extrapolation. - return Y[0] + deriv0 * x; + return Y[0] + deriv0 * x; } else if(x >= xmax_shifted) { // Right extrapolation. - return Y[N-1] + derivN * (x - xmax_shifted); + return Y[N-1] + derivN * (x - xmax_shifted); } else { #if SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES - // Do interval search. - int klo = 0; - int khi = N-1; - while(khi - klo > 1) { - int k = (khi + klo) / 2; - if(Xs[k] > x) khi = k; - else klo = k; - } - double h = Xs[khi] - Xs[klo]; - // Do spline interpolation. - double a = (Xs[khi] - x)/h; - double b = 1.0 - a; // = (x - X[klo])/h - return a * Y[klo] + b * Y[khi] + ((a*a*a - a) * Y2[klo] + (b*b*b - b) * Y2[khi])*(h*h)/6.0; + // Do interval search. + int klo = 0; + int khi = N-1; + while(khi - klo > 1) { + int k = (khi + klo) / 2; + if(Xs[k] > x) khi = k; + else klo = k; + } + double h = Xs[khi] - Xs[klo]; + // Do spline interpolation. + double a = (Xs[khi] - x)/h; + double b = 1.0 - a; // = (x - X[klo])/h + return a * Y[klo] + b * Y[khi] + + ((a*a*a - a) * Y2[klo] + (b*b*b - b) * Y2[khi])*(h*h)/6.0; #else - // For a spline with grid points, we can directly calculate the interval X is in. - int klo = (int)(x / h); - int khi = klo + 1; - double a = Xs[khi] - x; - double b = h - a; - return Y[khi] - a * Ydelta[klo] + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); + // For a spline with regular grid, we directly calculate the interval X is in. + int klo = (int)(x / h); + int khi = klo + 1; + double a = Xs[khi] - x; + double b = h - a; + return Y[khi] - a * Ydelta[klo] + + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); #endif } } @@ -150,37 +154,43 @@ protected: { x -= xmin; if(x <= 0.0) { // Left extrapolation. - deriv = deriv0; - return Y[0] + deriv0 * x; + deriv = deriv0; + return Y[0] + deriv0 * x; } else if(x >= xmax_shifted) { // Right extrapolation. - deriv = derivN; - return Y[N-1] + derivN * (x - xmax_shifted); + deriv = derivN; + return Y[N-1] + derivN * (x - xmax_shifted); } else { #if SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES - // Do interval search. - int klo = 0; - int khi = N-1; - while(khi - klo > 1) { - int k = (khi + klo) / 2; - if(Xs[k] > x) khi = k; - else klo = k; - } - double h = Xs[khi] - Xs[klo]; - // Do spline interpolation. - double a = (Xs[khi] - x)/h; - double b = 1.0 - a; // = (x - X[klo])/h - deriv = (Y[khi] - Y[klo]) / h + ((3.0*b*b - 1.0) * Y2[khi] - (3.0*a*a - 1.0) * Y2[klo]) * h / 6.0; - return a * Y[klo] + b * Y[khi] + ((a*a*a - a) * Y2[klo] + (b*b*b - b) * Y2[khi]) * (h*h) / 6.0; + // Do interval search. + int klo = 0; + int khi = N-1; + while(khi - klo > 1) { + int k = (khi + klo) / 2; + if(Xs[k] > x) khi = k; + else klo = k; + } + double h = Xs[khi] - Xs[klo]; + // Do spline interpolation. + double a = (Xs[khi] - x)/h; + double b = 1.0 - a; // = (x - X[klo])/h + deriv = (Y[khi] - Y[klo]) / h + + ((3.0*b*b - 1.0) * Y2[khi] - + (3.0*a*a - 1.0) * Y2[klo]) * h / 6.0; + return a * Y[klo] + b * Y[khi] + + ((a*a*a - a) * Y2[klo] + + (b*b*b - b) * Y2[khi]) * (h*h) / 6.0; #else - // For a spline with grid points, we can directly calculate the interval X is in. - int klo = (int)(x / h); - int khi = klo + 1; - double a = Xs[khi] - x; - double b = h - a; - deriv = Ydelta[klo] + ((3.0*b*b - hsq) * Y2[khi] - (3.0*a*a - hsq) * Y2[klo]); - return Y[khi] - a * Ydelta[klo] + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); + // For a spline with regular grid, we directly calculate the interval X is in. + int klo = (int)(x / h); + int khi = klo + 1; + double a = Xs[khi] - x; + double b = h - a; + deriv = Ydelta[klo] + ((3.0*b*b - hsq) * Y2[khi] + - (3.0*a*a - hsq) * Y2[klo]); + return Y[khi] - a * Ydelta[klo] + + ((a*a - hsq) * a * Y2[klo] + (b*b - hsq) * b * Y2[khi]); #endif } } @@ -198,20 +208,20 @@ protected: void communicate(MPI_Comm& world, int me); private: - double* X; // Positions of spline knots - double* Xs; // Shifted positions of spline knots - double* Y; // Function values at spline knots - double* Y2; // Second derivatives at spline knots - double* Ydelta; // If this is a grid spline, Ydelta[i] = (Y[i+1]-Y[i])/h - int N; // Number of spline knots - double deriv0; // First derivative at knot 0 - double derivN; // First derivative at knot (N-1) - double xmin; // The beginning of the interval on which the spline function is defined. - double xmax; // The end of the interval on which the spline function is defined. - int isGridSpline; // Indicates that all spline knots are on a regular grid. - double h; // The distance between knots if this is a grid spline with equidistant knots. - double hsq; // The squared distance between knots if this is a grid spline with equidistant knots. - double xmax_shifted; // The end of the spline interval after it has been shifted to begin at X=0. + double* X; // Positions of spline knots + double* Xs; // Shifted positions of spline knots + double* Y; // Function values at spline knots + double* Y2; // Second derivatives at spline knots + double* Ydelta; // If this is a grid spline, Ydelta[i] = (Y[i+1]-Y[i])/h + int N; // Number of spline knots + double deriv0; // First derivative at knot 0 + double derivN; // First derivative at knot (N-1) + double xmin; // The beginning of the interval on which the spline function is defined. + double xmax; // The end of the interval on which the spline function is defined. + int isGridSpline;// Indicates that all spline knots are on a regular grid. + double h; // The distance between knots if this is a grid spline with equidistant knots. + double hsq; // The squared distance between knots if this is a grid spline with equidistant knots. + double xmax_shifted; // The end of the spline interval after it has been shifted to begin at X=0. }; /// Helper data structure for potential routine. @@ -222,19 +232,19 @@ protected: double del[3]; }; - SplineFunction* phis; // Phi_i(r_ij) - SplineFunction* rhos; // Rho_ij(r_ij) - SplineFunction* fs; // f_i(r_ij) - SplineFunction* Us; // U_i(rho) - SplineFunction* gs; // g_ij(cos_theta) - double* zero_atom_energies; // Shift embedding energy by this value to make it zero for a single atom in vacuum. + SplineFunction* phis; // Phi_i(r_ij) + SplineFunction* rhos; // Rho_ij(r_ij) + SplineFunction* fs; // f_i(r_ij) + SplineFunction* Us; // U_i(rho) + SplineFunction* gs; // g_ij(cos_theta) + double* zero_atom_energies; // Shift embedding energy by this value to make it zero for a single atom in vacuum. - double cutoff; // The cutoff radius + double cutoff; // The cutoff radius - double* Uprime_values; // Used for temporary storage of U'(rho) values - int nmax; // Size of temporary array. - int maxNeighbors; // The last maximum number of neighbors a single atoms has. - MEAM2Body* twoBodyInfo; // Temporary array. + double* Uprime_values; // Used for temporary storage of U'(rho) values + int nmax; // Size of temporary array. + int maxNeighbors; // The last maximum number of neighbors a single atoms has. + MEAM2Body* twoBodyInfo; // Temporary array. void read_file(const char* filename); void allocate(); diff --git a/src/USER-OMP/pair_meam_spline_omp.cpp b/src/USER-OMP/pair_meam_spline_omp.cpp index b4e0c48acc..6e90dac66f 100644 --- a/src/USER-OMP/pair_meam_spline_omp.cpp +++ b/src/USER-OMP/pair_meam_spline_omp.cpp @@ -140,25 +140,21 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) nextTwoBodyInfo->tag = j; nextTwoBodyInfo->r = rij; - // nextTwoBodyInfo->f = f.eval(rij, nextTwoBodyInfo->fprime); - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); nextTwoBodyInfo->del[0] = jdelx / rij; nextTwoBodyInfo->del[1] = jdely / rij; nextTwoBodyInfo->del[2] = jdelz / rij; for(int kk = 0; kk < numBonds; kk++) { const MEAM2Body& bondk = myTwoBodyInfo[kk]; - double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + - nextTwoBodyInfo->del[1]*bondk.del[1] + - nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); - // double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + nextTwoBodyInfo->del[1]*bondk.del[1] + nextTwoBodyInfo->del[2]*bondk.del[2]); - // partial_sum += bondk.f * g.eval(cos_theta); + double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + + nextTwoBodyInfo->del[1]*bondk.del[1] + + nextTwoBodyInfo->del[2]*bondk.del[2]); + partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); } rho_value += nextTwoBodyInfo->f * partial_sum; - // rho_value += rho.eval(rij); - rho_value += rhos[i_to_potl(j)].eval(rij); + rho_value += rhos[i_to_potl(j)].eval(rij); numBonds++; nextTwoBodyInfo++; @@ -167,7 +163,6 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) // Compute embedding energy and its derivative. double Uprime_i; - // double embeddingEnergy = U.eval(rho_value, Uprime_i) - zero_atom_energy; double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) - zero_atom_energies[i_to_potl(i)]; Uprime_thr[i] = Uprime_i; @@ -195,8 +190,7 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) + bondj.del[1]*bondk->del[1] + bondj.del[2]*bondk->del[2]); double g_prime; - // double g_value = g.eval(cos_theta, g_prime); - double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); + double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); const double f_rik_prime = bondk->fprime; const double f_rik = bondk->f; @@ -301,20 +295,15 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) if(rij_sq < cutforcesq) { double rij = sqrt(rij_sq); - // double rho_prime; - // rho.eval(rij, rho_prime); - // double fpair = rho_prime * (Uprime_values[i] + Uprime_values[j]); double rho_prime_i,rho_prime_j; rhos[i_to_potl(i)].eval(rij,rho_prime_i); rhos[i_to_potl(j)].eval(rij,rho_prime_j); double fpair = rho_prime_j * Uprime_values[i] + rho_prime_i*Uprime_values[j]; - - // double pair_pot_deriv; - // double pair_pot = phi.eval(rij, pair_pot_deriv); + double pair_pot_deriv; double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); - fpair += pair_pot_deriv; + fpair += pair_pot_deriv; // Divide by r_ij to get forces from gradient. fpair /= rij; From 9cd994f57c701c7e28cc82c38c20edfd0a5cedc2 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 May 2017 15:35:48 -0400 Subject: [PATCH 23/26] fix issues with potential file parser - use Force::open_potential() - replace ftell()/fseek() with rewind()/fgets() which is safer on windows and other platforms with automatic CR/LF to LF conversion on text files - make parser use properly NULL terminated strings through using strtok() --- src/USER-MISC/pair_meam_spline.cpp | 52 ++++++++++++++++-------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 6fbff31753..e2f9209685 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -45,9 +45,6 @@ #include "neigh_request.h" #include "memory.h" #include "error.h" -#include - -using namespace std; using namespace LAMMPS_NS; @@ -449,7 +446,7 @@ void PairMEAMSpline::read_file(const char* filename) int nmultichoose2; // = (n+1)*n/2; if(comm->me == 0) { - FILE *fp = fopen(filename, "r"); + FILE *fp = force->open_potential(filename); if(fp == NULL) { char str[1024]; sprintf(str,"Cannot open spline MEAM potential file %s", filename); @@ -458,31 +455,35 @@ void PairMEAMSpline::read_file(const char* filename) // Skip first line of file. It's a comment. char line[MAXLINE]; + char *ptr; fgets(line, MAXLINE, fp); - // Second line holds potential type ("meam/spline") in new potential format. - bool isNewFormat; - long loc = ftell(fp); + // Second line holds potential type ("meam/spline") + // in new potential format. + + bool isNewFormat = false; fgets(line, MAXLINE, fp); - if (strncmp(line, "meam/spline", 11) == 0) { + ptr = strtok(line, " \t\n\r\f"); + + if (strcmp(ptr, "meam/spline") == 0) { isNewFormat = true; // parse the rest of the line! - char *linep = line+12, *word; - const char *sep = " ,;:-\t\n"; // overkill, but safe - word = strsep(&linep, sep); - if (! *word) - error->one(FLERR, "Need to include number of atomic species on meam/spline line in potential file"); - int n = atoi(word); - if (n<1) - error->one(FLERR, "Invalid number of atomic species on meam/spline line in potential file"); - nelements = n; - elements = new char*[n]; - for (int i=0; ione(FLERR, "Not enough atomic species in meam/spline\n"); - elements[i] = new char[strlen(word)+1]; - strcpy(elements[i], word); + ptr = strtok(NULL," \t\n\r\f"); + if (ptr == NULL) + error->one(FLERR,"Need to include number of atomic species on" + " meam/spline line in multi-element potential file"); + nelements = atoi(ptr); + if (nelements < 1) + error->one(FLERR, "Invalid number of atomic species on" + " meam/spline line in potential file"); + elements = new char*[nelements]; + for (int i=0; ione(FLERR, "Not enough atomic species in meam/spline" + " line of multi-element potential file"); + elements[i] = new char[strlen(ptr)+1]; + strcpy(elements[i], ptr); } } else { isNewFormat = false; @@ -490,7 +491,8 @@ void PairMEAMSpline::read_file(const char* filename) elements = new char*[1]; elements[0] = new char[1]; strcpy(elements[0], ""); - fseek(fp, loc, SEEK_SET); + rewind(fp); + fgets(line, MAXLINE, fp); } nmultichoose2 = ((nelements+1)*nelements)/2; From 6c5edf6c709ef1fc9c914ec8049fa41a7fb3a49a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 May 2017 15:38:10 -0400 Subject: [PATCH 24/26] performance improvement through avoiding function call and dereference overhead - make i_to_potl() and ij_to_potl() functions inline and const - don't dereference inside the functions, but cache, if possible in external variables => up to 15% speedup. --- src/USER-MISC/pair_meam_spline.cpp | 48 +++++++++++---------------- src/USER-MISC/pair_meam_spline.h | 7 ++-- src/USER-OMP/pair_meam_spline_omp.cpp | 24 +++++++++----- 3 files changed, 39 insertions(+), 40 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index e2f9209685..5c13b67d0a 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -99,8 +99,9 @@ PairMEAMSpline::~PairMEAMSpline() void PairMEAMSpline::compute(int eflag, int vflag) { - double** const x = atom->x; - double** forces = atom->f; + const double* const * const x = atom->x; + double* const * const forces = atom->f; + const int ntypes = atom->ntypes; if (eflag || vflag) { ev_setup(eflag, vflag); @@ -144,6 +145,9 @@ void PairMEAMSpline::compute(int eflag, int vflag) // compute charge density and numBonds MEAM2Body* nextTwoBodyInfo = twoBodyInfo; double rho_value = 0; + const int ntypes = atom->ntypes; + const int itype = atom->type[i]; + for(int jj = 0; jj < listfull->numneigh[i]; jj++) { int j = listfull->firstneigh[i][jj]; j &= NEIGHMASK; @@ -156,10 +160,11 @@ void PairMEAMSpline::compute(int eflag, int vflag) if(rij_sq < cutoff*cutoff) { double rij = sqrt(rij_sq); double partial_sum = 0; + const int jtype = atom->type[j]; nextTwoBodyInfo->tag = j; nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->f = fs[i_to_potl(jtype)].eval(rij, nextTwoBodyInfo->fprime); nextTwoBodyInfo->del[0] = jdelx / rij; nextTwoBodyInfo->del[1] = jdely / rij; nextTwoBodyInfo->del[2] = jdelz / rij; @@ -169,11 +174,11 @@ void PairMEAMSpline::compute(int eflag, int vflag) double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + nextTwoBodyInfo->del[1]*bondk.del[1] + nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); + partial_sum += bondk.f * gs[ij_to_potl(jtype,atom->type[bondk.tag],ntypes)].eval(cos_theta); } rho_value += nextTwoBodyInfo->f * partial_sum; - rho_value += rhos[i_to_potl(j)].eval(rij); + rho_value += rhos[i_to_potl(jtype)].eval(rij); numBonds++; nextTwoBodyInfo++; @@ -182,8 +187,8 @@ void PairMEAMSpline::compute(int eflag, int vflag) // Compute embedding energy and its derivative double Uprime_i; - double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) - - zero_atom_energies[i_to_potl(i)]; + double embeddingEnergy = Us[i_to_potl(itype)].eval(rho_value, Uprime_i) + - zero_atom_energies[i_to_potl(itype)]; Uprime_values[i] = Uprime_i; if(eflag) { @@ -204,6 +209,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) double f_rij = bondj.f; double forces_j[3] = {0, 0, 0}; + const int jtype = atom->type[j]; MEAM2Body const* bondk = twoBodyInfo; for(int kk = 0; kk < jj; kk++, ++bondk) { @@ -213,7 +219,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) bondj.del[1]*bondk->del[1] + bondj.del[2]*bondk->del[2]); double g_prime; - double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); + double g_value = gs[ij_to_potl(jtype,atom->type[bondk->tag],ntypes)].eval(cos_theta, g_prime); double f_rik_prime = bondk->fprime; double f_rik = bondk->f; @@ -280,6 +286,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) // Compute two-body pair interactions for(int ii = 0; ii < listhalf->inum; ii++) { int i = listhalf->ilist[ii]; + const int itype = atom->type[i]; for(int jj = 0; jj < listhalf->numneigh[i]; jj++) { int j = listhalf->firstneigh[i][jj]; @@ -293,13 +300,14 @@ void PairMEAMSpline::compute(int eflag, int vflag) if(rij_sq < cutoff*cutoff) { double rij = sqrt(rij_sq); + const int jtype = atom->type[j]; double rho_prime_i,rho_prime_j; - rhos[i_to_potl(i)].eval(rij,rho_prime_i); - rhos[i_to_potl(j)].eval(rij,rho_prime_j); + rhos[i_to_potl(itype)].eval(rij,rho_prime_i); + rhos[i_to_potl(jtype)].eval(rij,rho_prime_j); double fpair = rho_prime_j * Uprime_values[i] + rho_prime_i*Uprime_values[j]; double pair_pot_deriv; - double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); + double pair_pot = phis[ij_to_potl(itype,jtype,ntypes)].eval(rij, pair_pot_deriv); fpair += pair_pot_deriv; @@ -323,24 +331,6 @@ void PairMEAMSpline::compute(int eflag, int vflag) virial_fdotr_compute(); } - -/* ---------------------------------------------------------------------- - helper functions to map atom types to potential array indices -------------------------------------------------------------------------- */ - -int PairMEAMSpline::ij_to_potl(int i, int j) { - int n = atom->ntypes; - int itype = atom->type[i]; - int jtype = atom->type[j]; - - return jtype - 1 + (itype-1)*n - (itype-1)*itype/2; -} - -int PairMEAMSpline::i_to_potl(int i) { - int itype = atom->type[i]; - return itype - 1; -} - /* ---------------------------------------------------------------------- */ void PairMEAMSpline::allocate() diff --git a/src/USER-MISC/pair_meam_spline.h b/src/USER-MISC/pair_meam_spline.h index 31f64cc3e5..bbce38c211 100644 --- a/src/USER-MISC/pair_meam_spline.h +++ b/src/USER-MISC/pair_meam_spline.h @@ -54,8 +54,11 @@ public: // helper functions for compute() - int ij_to_potl(int i, int j); - int i_to_potl(int i); + int ij_to_potl(const int itype, const int jtype, const int ntypes) const { + return jtype - 1 + (itype-1)*ntypes - (itype-1)*itype/2; + } + int i_to_potl(const int itype) const { return itype-1; } + int pack_forward_comm(int, int *, double *, int, int *); void unpack_forward_comm(int, int, double *); diff --git a/src/USER-OMP/pair_meam_spline_omp.cpp b/src/USER-OMP/pair_meam_spline_omp.cpp index 6e90dac66f..96d602845d 100644 --- a/src/USER-OMP/pair_meam_spline_omp.cpp +++ b/src/USER-OMP/pair_meam_spline_omp.cpp @@ -110,6 +110,7 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) const int nthreads = comm->nthreads; const int nlocal = atom->nlocal; const int nall = nlocal + atom->nghost; + const int ntypes = atom->ntypes; const double cutforcesq = cutoff*cutoff; @@ -135,12 +136,13 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) const double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; if (rij_sq < cutforcesq) { + const int jtype = atom->type[j]; const double rij = sqrt(rij_sq); double partial_sum = 0; nextTwoBodyInfo->tag = j; nextTwoBodyInfo->r = rij; - nextTwoBodyInfo->f = fs[i_to_potl(j)].eval(rij, nextTwoBodyInfo->fprime); + nextTwoBodyInfo->f = fs[i_to_potl(jtype)].eval(rij, nextTwoBodyInfo->fprime); nextTwoBodyInfo->del[0] = jdelx / rij; nextTwoBodyInfo->del[1] = jdely / rij; nextTwoBodyInfo->del[2] = jdelz / rij; @@ -150,21 +152,22 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + nextTwoBodyInfo->del[1]*bondk.del[1] + nextTwoBodyInfo->del[2]*bondk.del[2]); - partial_sum += bondk.f * gs[ij_to_potl(j,bondk.tag)].eval(cos_theta); + partial_sum += bondk.f * gs[ij_to_potl(jtype,atom->type[bondk.tag],ntypes)].eval(cos_theta); } rho_value += nextTwoBodyInfo->f * partial_sum; - rho_value += rhos[i_to_potl(j)].eval(rij); + rho_value += rhos[i_to_potl(jtype)].eval(rij); numBonds++; nextTwoBodyInfo++; } } + const int itype = atom->type[i]; // Compute embedding energy and its derivative. double Uprime_i; - double embeddingEnergy = Us[i_to_potl(i)].eval(rho_value, Uprime_i) - - zero_atom_energies[i_to_potl(i)]; + double embeddingEnergy = Us[i_to_potl(itype)].eval(rho_value, Uprime_i) + - zero_atom_energies[i_to_potl(itype)]; Uprime_thr[i] = Uprime_i; if (EFLAG) e_tally_thr(this,i,i,nlocal,1/*newton_pair*/,embeddingEnergy,0.0,thr); @@ -176,6 +179,7 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) const MEAM2Body bondj = myTwoBodyInfo[jj]; const double rij = bondj.r; const int j = bondj.tag; + const int jtype = atom->type[j]; const double f_rij_prime = bondj.fprime; const double f_rij = bondj.f; @@ -190,7 +194,7 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) + bondj.del[1]*bondk->del[1] + bondj.del[2]*bondk->del[2]); double g_prime; - double g_value = gs[ij_to_potl(j,bondk->tag)].eval(cos_theta, g_prime); + double g_value = gs[ij_to_potl(jtype,atom->type[bondk->tag],ntypes)].eval(cos_theta, g_prime); const double f_rik_prime = bondk->fprime; const double f_rik = bondk->f; @@ -282,6 +286,7 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) const double ztmp = x[i][2]; const int* const jlist = firstneigh_half[i]; const int jnum = numneigh_half[i]; + const int itype = atom->type[i]; for(int jj = 0; jj < jnum; jj++) { const int j = jlist[jj] & NEIGHMASK; @@ -294,14 +299,15 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) if(rij_sq < cutforcesq) { double rij = sqrt(rij_sq); + const int jtype = atom->type[j]; double rho_prime_i,rho_prime_j; - rhos[i_to_potl(i)].eval(rij,rho_prime_i); - rhos[i_to_potl(j)].eval(rij,rho_prime_j); + rhos[i_to_potl(itype)].eval(rij,rho_prime_i); + rhos[i_to_potl(jtype)].eval(rij,rho_prime_j); double fpair = rho_prime_j * Uprime_values[i] + rho_prime_i*Uprime_values[j]; double pair_pot_deriv; - double pair_pot = phis[ij_to_potl(i,j)].eval(rij, pair_pot_deriv); + double pair_pot = phis[ij_to_potl(itype,jtype,ntypes)].eval(rij, pair_pot_deriv); fpair += pair_pot_deriv; From 390ceb1475a73636bf86e6de7e8493fa75c79e5a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 May 2017 15:49:37 -0400 Subject: [PATCH 25/26] whitespace cleanup --- src/USER-MISC/pair_meam_spline.cpp | 102 +++++++++++++------------- src/USER-MISC/pair_meam_spline.h | 46 ++++++------ src/USER-OMP/pair_meam_spline_omp.cpp | 2 +- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/USER-MISC/pair_meam_spline.cpp b/src/USER-MISC/pair_meam_spline.cpp index 5c13b67d0a..0148ed51cb 100644 --- a/src/USER-MISC/pair_meam_spline.cpp +++ b/src/USER-MISC/pair_meam_spline.cpp @@ -102,7 +102,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) const double* const * const x = atom->x; double* const * const forces = atom->f; const int ntypes = atom->ntypes; - + if (eflag || vflag) { ev_setup(eflag, vflag); } else { @@ -123,7 +123,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) int newMaxNeighbors = 0; for(int ii = 0; ii < listfull->inum; ii++) { int jnum = listfull->numneigh[listfull->ilist[ii]]; - if(jnum > newMaxNeighbors) + if(jnum > newMaxNeighbors) newMaxNeighbors = jnum; } @@ -151,24 +151,24 @@ void PairMEAMSpline::compute(int eflag, int vflag) for(int jj = 0; jj < listfull->numneigh[i]; jj++) { int j = listfull->firstneigh[i][jj]; j &= NEIGHMASK; - + double jdelx = x[j][0] - x[i][0]; double jdely = x[j][1] - x[i][1]; double jdelz = x[j][2] - x[i][2]; double rij_sq = jdelx*jdelx + jdely*jdely + jdelz*jdelz; - + if(rij_sq < cutoff*cutoff) { double rij = sqrt(rij_sq); double partial_sum = 0; const int jtype = atom->type[j]; - + nextTwoBodyInfo->tag = j; nextTwoBodyInfo->r = rij; nextTwoBodyInfo->f = fs[i_to_potl(jtype)].eval(rij, nextTwoBodyInfo->fprime); nextTwoBodyInfo->del[0] = jdelx / rij; nextTwoBodyInfo->del[1] = jdely / rij; nextTwoBodyInfo->del[2] = jdelz / rij; - + for(int kk = 0; kk < numBonds; kk++) { const MEAM2Body& bondk = twoBodyInfo[kk]; double cos_theta = (nextTwoBodyInfo->del[0]*bondk.del[0] + @@ -176,10 +176,10 @@ void PairMEAMSpline::compute(int eflag, int vflag) nextTwoBodyInfo->del[2]*bondk.del[2]); partial_sum += bondk.f * gs[ij_to_potl(jtype,atom->type[bondk.tag],ntypes)].eval(cos_theta); } - + rho_value += nextTwoBodyInfo->f * partial_sum; rho_value += rhos[i_to_potl(jtype)].eval(rij); - + numBonds++; nextTwoBodyInfo++; } @@ -189,7 +189,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) double Uprime_i; double embeddingEnergy = Us[i_to_potl(itype)].eval(rho_value, Uprime_i) - zero_atom_energies[i_to_potl(itype)]; - + Uprime_values[i] = Uprime_i; if(eflag) { if(eflag_global) @@ -204,17 +204,17 @@ void PairMEAMSpline::compute(int eflag, int vflag) const MEAM2Body bondj = twoBodyInfo[jj]; double rij = bondj.r; int j = bondj.tag; - + double f_rij_prime = bondj.fprime; double f_rij = bondj.f; - + double forces_j[3] = {0, 0, 0}; const int jtype = atom->type[j]; - + MEAM2Body const* bondk = twoBodyInfo; for(int kk = 0; kk < jj; kk++, ++bondk) { double rik = bondk->r; - + double cos_theta = (bondj.del[0]*bondk->del[0] + bondj.del[1]*bondk->del[1] + bondj.del[2]*bondk->del[2]); @@ -222,37 +222,37 @@ void PairMEAMSpline::compute(int eflag, int vflag) double g_value = gs[ij_to_potl(jtype,atom->type[bondk->tag],ntypes)].eval(cos_theta, g_prime); double f_rik_prime = bondk->fprime; double f_rik = bondk->f; - + double fij = -Uprime_i * g_value * f_rik * f_rij_prime; double fik = -Uprime_i * g_value * f_rij * f_rik_prime; - + double prefactor = Uprime_i * f_rij * f_rik * g_prime; double prefactor_ij = prefactor / rij; double prefactor_ik = prefactor / rik; fij += prefactor_ij * cos_theta; fik += prefactor_ik * cos_theta; - + double fj[3], fk[3]; - + fj[0] = bondj.del[0] * fij - bondk->del[0] * prefactor_ij; fj[1] = bondj.del[1] * fij - bondk->del[1] * prefactor_ij; fj[2] = bondj.del[2] * fij - bondk->del[2] * prefactor_ij; forces_j[0] += fj[0]; forces_j[1] += fj[1]; forces_j[2] += fj[2]; - + fk[0] = bondk->del[0] * fik - bondj.del[0] * prefactor_ik; fk[1] = bondk->del[1] * fik - bondj.del[1] * prefactor_ik; fk[2] = bondk->del[2] * fik - bondj.del[2] * prefactor_ik; forces_i[0] -= fk[0]; forces_i[1] -= fk[1]; forces_i[2] -= fk[2]; - + int k = bondk->tag; forces[k][0] += fk[0]; forces[k][1] += fk[1]; forces[k][2] += fk[2]; - + if(evflag) { double delta_ij[3]; double delta_ik[3]; @@ -265,7 +265,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) ev_tally3(i, j, k, 0.0, 0.0, fj, fk, delta_ij, delta_ik); } } - + forces[i][0] -= forces_j[0]; forces[i][1] -= forces_j[1]; forces[i][2] -= forces_j[2]; @@ -273,7 +273,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) forces[j][1] += forces_j[1]; forces[j][2] += forces_j[2]; } - + forces[i][0] += forces_i[0]; forces[i][1] += forces_i[1]; forces[i][2] += forces_i[2]; @@ -287,17 +287,17 @@ void PairMEAMSpline::compute(int eflag, int vflag) for(int ii = 0; ii < listhalf->inum; ii++) { int i = listhalf->ilist[ii]; const int itype = atom->type[i]; - + for(int jj = 0; jj < listhalf->numneigh[i]; jj++) { int j = listhalf->firstneigh[i][jj]; j &= NEIGHMASK; - + double jdel[3]; jdel[0] = x[j][0] - x[i][0]; jdel[1] = x[j][1] - x[i][1]; jdel[2] = x[j][2] - x[i][2]; double rij_sq = jdel[0]*jdel[0] + jdel[1]*jdel[1] + jdel[2]*jdel[2]; - + if(rij_sq < cutoff*cutoff) { double rij = sqrt(rij_sq); const int jtype = atom->type[j]; @@ -327,7 +327,7 @@ void PairMEAMSpline::compute(int eflag, int vflag) } } - if(vflag_fdotr) + if(vflag_fdotr) virial_fdotr_compute(); } @@ -410,12 +410,12 @@ void PairMEAMSpline::coeff(int narg, char **arg) } } // clear setflag since coeff() called once with I,J = * * - + n = atom->ntypes; 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; @@ -442,19 +442,19 @@ void PairMEAMSpline::read_file(const char* filename) sprintf(str,"Cannot open spline MEAM potential file %s", filename); error->one(FLERR,str); } - + // Skip first line of file. It's a comment. char line[MAXLINE]; char *ptr; fgets(line, MAXLINE, fp); - + // Second line holds potential type ("meam/spline") // in new potential format. bool isNewFormat = false; fgets(line, MAXLINE, fp); ptr = strtok(line, " \t\n\r\f"); - + if (strcmp(ptr, "meam/spline") == 0) { isNewFormat = true; // parse the rest of the line! @@ -484,13 +484,13 @@ void PairMEAMSpline::read_file(const char* filename) rewind(fp); fgets(line, MAXLINE, fp); } - + nmultichoose2 = ((nelements+1)*nelements)/2; // allocate!! allocate(); - + // Parse spline functions. - + for (int i = 0; i < nmultichoose2; i++) phis[i].parse(fp, error, isNewFormat); for (int i = 0; i < nelements; i++) @@ -501,7 +501,7 @@ void PairMEAMSpline::read_file(const char* filename) fs[i].parse(fp, error, isNewFormat); for (int i = 0; i < nmultichoose2; i++) gs[i].parse(fp, error, isNewFormat); - + fclose(fp); } @@ -532,11 +532,11 @@ void PairMEAMSpline::read_file(const char* filename) Us[i].communicate(world, comm->me); for (int i = 0; i < nmultichoose2; i++) gs[i].communicate(world, comm->me); - + // Calculate 'zero-point energy' of single atom in vacuum. for (int i = 0; i < nelements; i++) zero_atom_energies[i] = Us[i].eval(0.0); - + // Determine maximum cutoff radius of all relevant spline functions. cutoff = 0.0; for (int i = 0; i < nmultichoose2; i++) @@ -548,7 +548,7 @@ void PairMEAMSpline::read_file(const char* filename) for (int i = 0; i < nelements; i++) if(fs[i].cutoff() > cutoff) cutoff = fs[i].cutoff(); - + // Set LAMMPS pair interaction flags. for(int i = 1; i <= atom->ntypes; i++) { for(int j = 1; j <= atom->ntypes; j++) { @@ -556,7 +556,7 @@ void PairMEAMSpline::read_file(const char* filename) cutsq[i][j] = cutoff; } } - + } /* ---------------------------------------------------------------------- @@ -643,27 +643,27 @@ void PairMEAMSpline::SplineFunction::parse(FILE* fp, Error* error, bool isNewFormat) { char line[MAXLINE]; - + // If new format, read the spline format. Should always be "spline3eq" for now. if (isNewFormat) fgets(line, MAXLINE, fp); - + // Parse number of spline knots. fgets(line, MAXLINE, fp); int n = atoi(line); if(n < 2) error->one(FLERR,"Invalid number of spline knots in MEAM potential file"); - + // Parse first derivatives at beginning and end of spline. fgets(line, MAXLINE, fp); double d0 = atof(strtok(line, " \t\n\r\f")); double dN = atof(strtok(NULL, " \t\n\r\f")); init(n, d0, dN); - + // Skip line in old format if (!isNewFormat) fgets(line, MAXLINE, fp); - + // Parse knot coordinates. for(int i=0; i 1e-8) isGridSpline = false; } - + double qn = 0.5; double un = (3.0/(X[N-1]-X[N-2])) * (derivN - (Y[N-1]-Y[N-2])/(X[N-1]-X[N-2])); Y2[N-1] = (un - qn*u[N-2]) / (qn * Y2[N-2] + 1.0); for(int k = N-2; k >= 0; k--) { Y2[k] = Y2[k] * Y2[k+1] + u[k]; } - + delete[] u; - + #if !SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES if(!isGridSpline) error->one(FLERR,"Support for MEAM potentials with non-uniform cubic splines has not been enabled in the MEAM potential code. Set SPLINE_MEAM_SUPPORT_NON_GRID_SPLINES in pair_spline_meam.h to 1 to enable it"); diff --git a/src/USER-MISC/pair_meam_spline.h b/src/USER-MISC/pair_meam_spline.h index bbce38c211..6200254674 100644 --- a/src/USER-MISC/pair_meam_spline.h +++ b/src/USER-MISC/pair_meam_spline.h @@ -51,21 +51,21 @@ public: void init_style(); void init_list(int, class NeighList *); double init_one(int, int); - + // helper functions for compute() - + int ij_to_potl(const int itype, const int jtype, const int ntypes) const { return jtype - 1 + (itype-1)*ntypes - (itype-1)*itype/2; } int i_to_potl(const int itype) const { return itype-1; } - - + + int pack_forward_comm(int, int *, double *, int, int *); void unpack_forward_comm(int, int, double *); int pack_reverse_comm(int, int, double *); void unpack_reverse_comm(int, int *, double *); double memory_usage(); - + protected: char **elements; // names of unique elements int *map; // mapping from atom types to elements @@ -75,7 +75,7 @@ protected: public: /// Default constructor. SplineFunction() : X(NULL), Xs(NULL), Y(NULL), Y2(NULL), Ydelta(NULL), N(0) {} - + /// Destructor. ~SplineFunction() { delete[] X; @@ -84,7 +84,7 @@ protected: delete[] Y2; delete[] Ydelta; } - + /// Initialization of spline function. void init(int _N, double _deriv0, double _derivN) { N = _N; @@ -101,19 +101,19 @@ protected: Y2 = new double[N]; Ydelta = new double[N]; } - + /// Adds a knot to the spline. void setKnot(int n, double x, double y) { X[n] = x; Y[n] = y; } - + /// Returns the number of knots. int numKnots() const { return N; } - + /// Parses the spline knots from a text file. void parse(FILE* fp, Error* error, bool isNewFormat); - + /// Calculates the second derivatives of the cubic spline. void prepareSpline(Error* error); - + /// Evaluates the spline function at position x. inline double eval(double x) const { @@ -151,7 +151,7 @@ protected: #endif } } - + /// Evaluates the spline function and its first derivative at position x. inline double eval(double x, double& deriv) const { @@ -197,16 +197,16 @@ protected: #endif } } - + /// Returns the number of bytes used by this function object. double memory_usage() const { return sizeof(*this) + sizeof(X[0]) * N * 3; } /// Returns the cutoff radius of this function. double cutoff() const { return X[N-1]; } - + /// Writes a Gnuplot script that plots the spline function. void writeGnuplot(const char* filename, const char* title = NULL) const; - + /// Broadcasts the spline function parameters to all processors. void communicate(MPI_Comm& world, int me); @@ -226,7 +226,7 @@ protected: double hsq; // The squared distance between knots if this is a grid spline with equidistant knots. double xmax_shifted; // The end of the spline interval after it has been shifted to begin at X=0. }; - + /// Helper data structure for potential routine. struct MEAM2Body { int tag; // holds the index of the second atom (j) @@ -234,26 +234,26 @@ protected: double f, fprime; double del[3]; }; - + SplineFunction* phis; // Phi_i(r_ij) SplineFunction* rhos; // Rho_ij(r_ij) SplineFunction* fs; // f_i(r_ij) SplineFunction* Us; // U_i(rho) SplineFunction* gs; // g_ij(cos_theta) double* zero_atom_energies; // Shift embedding energy by this value to make it zero for a single atom in vacuum. - + double cutoff; // The cutoff radius - + double* Uprime_values; // Used for temporary storage of U'(rho) values int nmax; // Size of temporary array. int maxNeighbors; // The last maximum number of neighbors a single atoms has. MEAM2Body* twoBodyInfo; // Temporary array. - + void read_file(const char* filename); void allocate(); - + }; - + } #endif diff --git a/src/USER-OMP/pair_meam_spline_omp.cpp b/src/USER-OMP/pair_meam_spline_omp.cpp index 96d602845d..4333d3b2a9 100644 --- a/src/USER-OMP/pair_meam_spline_omp.cpp +++ b/src/USER-OMP/pair_meam_spline_omp.cpp @@ -305,7 +305,7 @@ void PairMEAMSplineOMP::eval(int iifrom, int iito, ThrData * const thr) rhos[i_to_potl(itype)].eval(rij,rho_prime_i); rhos[i_to_potl(jtype)].eval(rij,rho_prime_j); double fpair = rho_prime_j * Uprime_values[i] + rho_prime_i*Uprime_values[j]; - + double pair_pot_deriv; double pair_pot = phis[ij_to_potl(itype,jtype,ntypes)].eval(rij, pair_pot_deriv); From d0da0639f02b65746a6bbb2ee69145c35f2ae12e Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Tue, 9 May 2017 15:51:59 -0400 Subject: [PATCH 26/26] add a couple of simple example single/multi-elment inputs for meam/spline pair styles --- .../USER/misc/meam_spline/Si_1.meam.spline | 63 +++++ .../USER/misc/meam_spline/TiO.meam.spline | 130 +++++++++ .../USER/misc/meam_spline/in.meam-spline.Si | 22 ++ .../USER/misc/meam_spline/in.meam-spline.TiO2 | 92 +++++++ .../log.4May2017.meam-spline.Si.g++.1 | 88 +++++++ .../log.4May2017.meam-spline.Si.g++.4 | 88 +++++++ .../log.4May2017.meam-spline.TiO2.g++.1 | 248 ++++++++++++++++++ .../log.4May2017.meam-spline.TiO2.g++.4 | 248 ++++++++++++++++++ 8 files changed, 979 insertions(+) create mode 100644 examples/USER/misc/meam_spline/Si_1.meam.spline create mode 100644 examples/USER/misc/meam_spline/TiO.meam.spline create mode 100644 examples/USER/misc/meam_spline/in.meam-spline.Si create mode 100644 examples/USER/misc/meam_spline/in.meam-spline.TiO2 create mode 100644 examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.1 create mode 100644 examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.4 create mode 100644 examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.1 create mode 100644 examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.4 diff --git a/examples/USER/misc/meam_spline/Si_1.meam.spline b/examples/USER/misc/meam_spline/Si_1.meam.spline new file mode 100644 index 0000000000..1ebd09cf84 --- /dev/null +++ b/examples/USER/misc/meam_spline/Si_1.meam.spline @@ -0,0 +1,63 @@ +DATE: 2012-02-01 CONTRIBUTOR: Alexander Stukowski, stukowski@mm.tu-darmstadt.de CITATION: Lenosky, Sadigh, Alonso, Bulatov, de la Rubia, Kim, Voter and Kress, Modell Simul Mater Sci Eng, 8, 825 (2000) COMMENT: Spline-based MEAM potential for Si. Reference: T. J. Lenosky, B. Sadigh, E. Alonso, V. V. Bulatov, T. D. de la Rubia, J. Kim, A. F. Voter, and J. D. Kress, Modell. Simul. Mater. Sci. Eng. 8, 825 (2000) +10 +-4.266966781858503300e+01 0.000000000000000000e+00 +1 0 1 0 +1.500000000000000000e+00 6.929943430771341000e+00 1.653321602557917600e+02 +1.833333333333333300e+00 -4.399503747408950400e-01 3.941543472528634600e+01 +2.166666666666666500e+00 -1.701233725061446700e+00 6.871065423413908100e+00 +2.500000000000000000e+00 -1.624732919215791800e+00 5.340648014033163800e+00 +2.833333333333333000e+00 -9.969641728342462100e-01 1.534811309391571000e+00 +3.166666666666667000e+00 -2.739141845072665100e-01 -6.334706186546093900e+00 +3.500000000000000000e+00 -2.499156963774082700e-02 -1.798864729909626500e+00 +3.833333333333333500e+00 -1.784331481529976400e-02 4.743496636420091500e-01 +4.166666666666666100e+00 -9.612303290166881000e-03 -4.006506271304824400e-02 +4.500000000000000000e+00 0.000000000000000000e+00 -2.394996574779807200e-01 +11 +-1.000000000000000000e+00 0.000000000000000000e+00 +1 0 0 0 +1.500000000000000000e+00 1.374674212682983900e-01 -3.227795813279568500e+00 +1.700000000000000000e+00 -1.483141815327918000e-01 -6.411648793604404900e+00 +1.899999999999999900e+00 -5.597204896096039700e-01 1.003068519633888300e+01 +2.100000000000000100e+00 -7.310964379372824100e-01 2.293461970618954700e+00 +2.299999999999999800e+00 -7.628287071954063000e-01 1.742018781618444500e+00 +2.500000000000000000e+00 -7.291769685066557000e-01 5.460640949384478700e-01 +2.700000000000000200e+00 -6.662022220044453400e-01 4.721760106467195500e-01 +2.899999999999999900e+00 -5.732830582550895200e-01 2.056894449546524200e+00 +3.100000000000000100e+00 -4.069014309729406300e-01 2.319615721086100800e+00 +3.299999999999999800e+00 -1.666155295956388300e-01 -2.497162196179187900e-01 +3.500000000000000000e+00 0.000000000000000000e+00 -1.237130660986393100e+01 +8 +7.351364478015182100e-01 6.165217237728655200e-01 +1 1 1 1 +-1.770934559908718700e+00 -1.074925682941420000e+00 -1.482768170233858500e-01 +-3.881557649503457600e-01 -2.004503493658201000e-01 -1.492100354067345500e-01 +9.946230300080272100e-01 4.142241371345077300e-01 -7.012475119623896900e-02 +2.377401824966400000e+00 8.793892953828742500e-01 -3.944355024164965900e-02 +3.760180619924772900e+00 1.266888024536562100e+00 -1.581431192239436000e-02 +5.142959414883146800e+00 1.629979548834614900e+00 2.611224310900800400e-02 +6.525738209841518900e+00 1.977379549636293600e+00 -1.378738550324104500e-01 +7.908517004799891800e+00 2.396177220616657200e+00 7.494253977092666400e-01 +10 +-3.618936018538757300e+00 0.000000000000000000e+00 +1 0 1 0 +1.500000000000000000e+00 1.250311510312851300e+00 2.790400588857243500e+01 +1.722222222222222300e+00 8.682060369372680600e-01 -4.522554291731776900e+00 +1.944444444444444400e+00 6.084604017544847900e-01 5.052931618779816800e+00 +2.166666666666666500e+00 4.875624808097850400e-01 1.180825096539679600e+00 +2.388888888888888800e+00 4.416345603457190700e-01 -6.673769465415171400e-01 +2.611111111111111200e+00 3.760976313325982700e-01 -8.938118490837722000e-01 +2.833333333333333000e+00 2.714524157414608400e-01 -5.090324763524399800e-01 +3.055555555555555400e+00 1.481440300150710900e-01 6.623665830603995300e-01 +3.277777777777777700e+00 4.854596610856590900e-02 7.403702452268122700e-01 +3.500000000000000000e+00 0.000000000000000000e+00 2.578982318481970500e+00 +8 +-1.395041572145673000e+01 1.134616739799360700e+00 +1 1 1 1 +-1.000000000000000900e+00 5.254163992149617700e+00 1.582685381253900500e+01 +-7.428367052748285900e-01 2.359149452448745100e+00 3.117611233789983400e+01 +-4.856734105496561800e-01 1.195946960915646100e+00 1.658962813584905800e+01 +-2.285101158244838800e-01 1.229952028074150000e+00 1.108360928564026400e+01 +2.865317890068852500e-02 2.035650777568434500e+00 9.088861456447702400e+00 +2.858164736258610400e-01 3.424741418405580000e+00 5.489943377538379500e+00 +5.429797683510331200e-01 4.948585892304984100e+00 -1.882291580187675700e+01 +8.001430630762056400e-01 5.617988713941801200e+00 -7.718625571850646200e+00 diff --git a/examples/USER/misc/meam_spline/TiO.meam.spline b/examples/USER/misc/meam_spline/TiO.meam.spline new file mode 100644 index 0000000000..ed2a67a962 --- /dev/null +++ b/examples/USER/misc/meam_spline/TiO.meam.spline @@ -0,0 +1,130 @@ +# Ti-O cubic spline potential where O is in the dilute limit. DATE: 2016-06-05 CONTRIBUTOR: Pinchao Zhang, Dallas R. Trinkle +meam/spline 2 Ti O +spline3eq +13 +-20 0 +1.742692837 3.744277175966 99.4865081627958 +2.05580176725 0.910839730906 10.8702523265355 +2.3689106975 0.388045896634 -1.55322418749562 +2.68201962775 -0.018840906533 2.43630041329215 +2.995128558 -0.248098929639 2.67912713976835 +3.30823748825 -0.264489550297 -0.125056384603077 +3.6213464185 -0.227196189283 1.10662555360438 +3.93445534875 -0.129293090176 -0.592053676745914 +4.247564279 -0.059685366933 -0.470123414607672 +4.56067320925 -0.031100025561 -0.0380739973059663 +4.8737821395 -0.013847363202 -0.0711547960695406 +5.18689106975 -0.003203412728 -0.081768292420175 +5.5 0 -0.0571422964883619 +spline3eq +5 +0.155001355787331 0 +1.9 0.533321679606674 0 +2.8 0.456402081843862 -1.60311717015859 +3.7 -0.324281383502201 1.19940299483249 +4.6 -0.474029826906675 1.47909794595154 +5.5 0 -2.49521499855605 +spline3eq +13 +0 0 +1.742692837 0 0 +2.05580176725 0 0 +2.3689106975 0 0 +2.68201962775 0 0 +2.995128558 0 0 +3.30823748825 0 0 +3.6213464185 0 0 +3.93445534875 0 0 +4.247564279 0 0 +4.56067320925 0 0 +4.8737821395 0 0 +5.18689106975 0 0 +5.5 0 0 +spline3eq +11 +-1 0 +2.055801767 1.7475279661 -525.869786904802 +2.2912215903 -5.8677963945 252.796316927755 +2.5266414136 -8.3376288737 71.7318388721015 +2.7620612369 -5.8398712842 -1.93587742753693 +2.9974810602 -3.1140648231 -39.2999192667503 +3.2329008835 -1.7257245065 14.3424136002004 +3.4683207068 -0.4428977017 -29.4925534559498 +3.7037405301 -0.1466643003 -3.18010534572236 +3.9391603534 -0.2095507945 3.33490838803603 +4.1745801767 -0.1442384563 3.71918691359508 +4.41 0 -9.66717019857564 +spline3eq +5 +-61.9827585211652 0 +1.9 11.2293641315584 0 +2.8 -27.9976343076148 122.648031332411 +3.7 -8.32979773113248 -54.3340881766381 +4.6 -1.00863195297399 3.23150064581724 +5.5 0 -5.3514242228123 +spline3eq +4 +0.00776934946045395 0.105197706160344 +-55.14233165 -0.29745568008 0.00152870603877451 +-44.7409899033333 -0.15449458722 0.00038933722543571 +-34.3396481566667 0.05098657168 0.00038124926922248 +-23.93830641 0.57342694704 0.0156639264890892 +spline3eq +5 +-0.00676745157022662 -0.0159520381982146 +-23.9928 0.297607384684645 0 +-15.9241175 0.216691597077105 -0.0024248755353942 +-7.855435 0.0637598673719069 0.00306245895013358 +0.213247499999998 -0.00183450621970427 -0.00177588407633909 +8.28193 -0.111277018874367 0 +spline3eq +10 +2.77327511656661 0 +2.055801767 -0.1485215264 72.2010867146919 +2.31737934844444 1.6845304918 -47.2744689053404 +2.57895692988889 2.0113365977 -15.1859578405326 +2.84053451133333 1.1444092747 3.33978204841873 +3.10211209277778 0.2861606803 2.587867603808 +3.36368967422222 -0.3459281126 6.14070694084556 +3.62526725566667 -0.6257480601 3.7397696717154 +3.88684483711111 -0.6119510826 4.64749084871402 +4.14842241855556 -0.3112059651 2.83275746415936 +4.41 0 -15.0612086827734 +spline3eq +5 +12.3315547862781 0 +1.9 2.62105440156724 0 +2.8 10.2850803058354 -25.439802988016 +3.7 3.23933763743897 -7.20203673434025 +4.6 -5.79049355858613 39.5509978688682 +5.5 0 -41.221771373642 +spline3eq +8 +8.33642274810572 -60.4024574736564 +-1 0.07651409193 -110.652321293778 +-0.724509054371429 0.14155824541 44.8853405500508 +-0.449018108742857 0.75788697341 -25.3065115342002 +-0.173527163114286 0.63011570378 -2.48510144915082 +0.101963782514286 0.09049597305 2.68769386908235 +0.377454728142857 -0.35741586657 -1.01558570129633 +0.652945673771428 -0.65293217647 13.4224786001212 +0.9284366194 -6.00912190653 -452.752542694929 +spline3eq +5 +0.137191606537625 -1.55094230968985 +-1 0.0513843442016519 0 +-0.5 0.0179024412245673 -2.44986494990154 +0 -0.260650876879273 3.91774583656401 +0.5 -0.190163791764901 -4.84414871911743 +1 -0.763795416646599 0 +spline3eq +8 +0 0 +-1 0 0 +-0.724509054371429 0 0 +-0.449018108742857 0 0 +-0.173527163114286 0 0 +0.101963782514286 0 0 +0.377454728142857 0 0 +0.652945673771428 0 0 +0.9284366194 0 0 diff --git a/examples/USER/misc/meam_spline/in.meam-spline.Si b/examples/USER/misc/meam_spline/in.meam-spline.Si new file mode 100644 index 0000000000..7f270ccecd --- /dev/null +++ b/examples/USER/misc/meam_spline/in.meam-spline.Si @@ -0,0 +1,22 @@ +# Si fcc phase + +units metal +boundary p p p + +atom_style atomic +lattice fcc 3.98 +region box block 0 5 0 5 0 5 +create_box 1 box +create_atoms 1 box + +pair_style meam/spline +pair_coeff * * Si_1.meam.spline Si +mass * 28.085 + +velocity all create 500.0 44226611 + +fix 1 all nvt temp 500.0 500.0 1.0 + +thermo 50 +run 500 + diff --git a/examples/USER/misc/meam_spline/in.meam-spline.TiO2 b/examples/USER/misc/meam_spline/in.meam-spline.TiO2 new file mode 100644 index 0000000000..06c8b7f8cd --- /dev/null +++ b/examples/USER/misc/meam_spline/in.meam-spline.TiO2 @@ -0,0 +1,92 @@ +# + +variable T_depart equal 300 + +variable dt equal 0.0002 + +variable a equal 4.5937 +variable c equal 2.9587 +variable ca equal ${c}/${a} + +variable nx equal 6 +variable ny equal 6 +variable nz equal 11 + +variable bx equal ${a}*${nx} +variable by equal ${a}*${ny} +variable bz equal ${c}*${nz} +# ======================================================================= + +units metal +atom_style atomic +dimension 3 +boundary p p p + + +lattice sc 1.0 +region box_vide prism 0 ${bx} 0 ${by} 0 ${bz} 0.0 0.0 0.0 +create_box 2 box_vide + +#lattice sc 1.0 +#region box_TiO2 block 0 ${bx} 0 ${by} 0 ${bz} + +# titanium atoms +lattice custom ${a} origin 0.0 0.0 0.0 & + orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 & + a1 1.0 0.0 0.0 & + a2 0.0 1.0 0.0 & + a3 0.0 0.0 ${ca} & + basis 0.0 0.0 0.0 & + basis 0.5 0.5 0.5 + +create_atoms 2 region box_vide + +# Oxygen atoms +lattice custom ${a} origin 0.0 0.0 0.0 & + orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 & + a1 1.0 0.0 0.0 & + a2 0.0 1.0 0.0 & + a3 0.0 0.0 ${ca} & + basis 0.30478 0.30478 0.0 & + basis 0.69522 0.69522 0.0 & + basis 0.19522 0.80478 0.5 & + basis 0.80478 0.19522 0.5 + +create_atoms 1 region box_vide + + +mass 1 16.00 +group Oxy type 1 + +mass 2 47.867 +group Ti type 2 + +velocity all create ${T_depart} 277387 + +pair_style meam/spline +pair_coeff * * TiO.meam.spline O Ti + +neighbor 0.5 bin +neigh_modify every 2 delay 0 check yes + +timestep ${dt} + +thermo_style custom step temp press pe ke etotal lx ly lz vol +thermo 10 + + +#dump 5 all custom 500 boxAlpha_alumina.lammpstrj id type q x y z + +fix 3 all nve +run 100 + +unfix 3 +fix 1 all box/relax tri 0.0 vmax 0.001 +minimize 1.0e-3 1.0e-5 1000 10000 + +unfix 1 +reset_timestep 0 +thermo 50 +fix 3 all npt temp 300 300 0.1 aniso 1.0 1.0 1.0 +run 500 + diff --git a/examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.1 b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.1 new file mode 100644 index 0000000000..ebf0855029 --- /dev/null +++ b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.1 @@ -0,0 +1,88 @@ +LAMMPS (13 Apr 2017) + using 1 OpenMP thread(s) per MPI task +# Si fcc phase + +units metal +boundary p p p + +atom_style atomic +lattice fcc 3.98 +Lattice spacing in x,y,z = 3.98 3.98 3.98 +region box block 0 5 0 5 0 5 +create_box 1 box +Created orthogonal box = (0 0 0) to (19.9 19.9 19.9) + 1 by 1 by 1 MPI processor grid +create_atoms 1 box +Created 500 atoms + +pair_style meam/spline +pair_coeff * * Si_1.meam.spline Si +Reading potential file Si_1.meam.spline with DATE: 2012-02-01 +mass * 28.085 + +velocity all create 500.0 44226611 + +fix 1 all nvt temp 500.0 500.0 1.0 + +thermo 50 +run 500 +Neighbor list info ... + update every 1 steps, delay 10 steps, check yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.5 + ghost atom cutoff = 6.5 + binsize = 3.25, bins = 7 7 7 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam/spline, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam/spline, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 3.892 | 3.892 | 3.892 Mbytes +Step Temp E_pair E_mol TotEng Press + 0 500 -1847.729 0 -1815.4786 1813162.7 + 50 1934.0932 -1940.8016 0 -1816.051 -48657.676 + 100 2570.1286 -1984.8725 0 -1819.0971 8002.4248 + 150 2566.7917 -1990.2724 0 -1824.7123 16819.447 + 200 2555.1319 -1995.2233 0 -1830.4152 5891.5313 + 250 2487.2881 -1995.8302 0 -1835.3981 -4339.7172 + 300 2381.4836 -1994.2492 0 -1840.6415 16508.04 + 350 2330.8663 -1996.6588 0 -1846.3161 24194.447 + 400 2212.6035 -1994.9278 0 -1852.2131 -9856.3709 + 450 2257.7531 -2003.8187 0 -1858.1918 -8029.6019 + 500 2211.4385 -2006.9846 0 -1864.345 4152.4867 +Loop time of 5.13837 on 1 procs for 500 steps with 500 atoms + +Performance: 8.407 ns/day, 2.855 hours/ns, 97.307 timesteps/s +99.8% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 5.0952 | 5.0952 | 5.0952 | 0.0 | 99.16 +Neigh | 0.026447 | 0.026447 | 0.026447 | 0.0 | 0.51 +Comm | 0.0063307 | 0.0063307 | 0.0063307 | 0.0 | 0.12 +Output | 0.0001905 | 0.0001905 | 0.0001905 | 0.0 | 0.00 +Modify | 0.0082877 | 0.0082877 | 0.0082877 | 0.0 | 0.16 +Other | | 0.00187 | | | 0.04 + +Nlocal: 500 ave 500 max 500 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 1767 ave 1767 max 1767 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 18059 ave 18059 max 18059 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 36118 ave 36118 max 36118 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 36118 +Ave neighs/atom = 72.236 +Neighbor list builds = 14 +Dangerous builds = 0 + +Total wall time: 0:00:05 diff --git a/examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.4 b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.4 new file mode 100644 index 0000000000..3f059d7cee --- /dev/null +++ b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.Si.g++.4 @@ -0,0 +1,88 @@ +LAMMPS (13 Apr 2017) + using 1 OpenMP thread(s) per MPI task +# Si fcc phase + +units metal +boundary p p p + +atom_style atomic +lattice fcc 3.98 +Lattice spacing in x,y,z = 3.98 3.98 3.98 +region box block 0 5 0 5 0 5 +create_box 1 box +Created orthogonal box = (0 0 0) to (19.9 19.9 19.9) + 1 by 2 by 2 MPI processor grid +create_atoms 1 box +Created 500 atoms + +pair_style meam/spline +pair_coeff * * Si_1.meam.spline Si +Reading potential file Si_1.meam.spline with DATE: 2012-02-01 +mass * 28.085 + +velocity all create 500.0 44226611 + +fix 1 all nvt temp 500.0 500.0 1.0 + +thermo 50 +run 500 +Neighbor list info ... + update every 1 steps, delay 10 steps, check yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6.5 + ghost atom cutoff = 6.5 + binsize = 3.25, bins = 7 7 7 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam/spline, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam/spline, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 3.861 | 3.861 | 3.861 Mbytes +Step Temp E_pair E_mol TotEng Press + 0 500 -1847.729 0 -1815.4786 1813162.7 + 50 1923.4262 -1940.0936 0 -1816.0311 -38700.835 + 100 2535.2542 -1982.6249 0 -1819.0989 10216.821 + 150 2592.8247 -1992.1569 0 -1824.9176 4839.3385 + 200 2484.7391 -1990.8452 0 -1830.5775 14040.141 + 250 2597.4401 -2003.1619 0 -1835.625 1261.5199 + 300 2513.0793 -2002.942 0 -1840.8463 6690.9815 + 350 2390.933 -2001.0761 0 -1846.859 -4880.1146 + 400 2269.0782 -1999.3441 0 -1852.9867 -4921.4391 + 450 2287.5096 -2006.8236 0 -1859.2774 -7313.6151 + 500 2303.0918 -2014.0693 0 -1865.518 -9995.1789 +Loop time of 1.46588 on 4 procs for 500 steps with 500 atoms + +Performance: 29.470 ns/day, 0.814 hours/ns, 341.093 timesteps/s +99.4% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 1.4273 | 1.4292 | 1.432 | 0.1 | 97.50 +Neigh | 0.0068567 | 0.0070301 | 0.0073655 | 0.2 | 0.48 +Comm | 0.019111 | 0.022127 | 0.024148 | 1.2 | 1.51 +Output | 0.00023174 | 0.00024784 | 0.00029206 | 0.0 | 0.02 +Modify | 0.005043 | 0.0052016 | 0.0054417 | 0.2 | 0.35 +Other | | 0.002066 | | | 0.14 + +Nlocal: 125 ave 131 max 118 min +Histogram: 1 0 0 1 0 0 0 0 1 1 +Nghost: 979.25 ave 986 max 975 min +Histogram: 1 1 0 1 0 0 0 0 0 1 +Neighs: 4541.75 ave 4712 max 4362 min +Histogram: 1 1 0 0 0 0 0 0 0 2 +FullNghs: 9083.5 ave 9485 max 8601 min +Histogram: 1 0 0 1 0 0 0 0 1 1 + +Total # of neighbors = 36334 +Ave neighs/atom = 72.668 +Neighbor list builds = 14 +Dangerous builds = 0 + +Total wall time: 0:00:01 diff --git a/examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.1 b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.1 new file mode 100644 index 0000000000..aaeadec668 --- /dev/null +++ b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.1 @@ -0,0 +1,248 @@ +LAMMPS (13 Apr 2017) + using 1 OpenMP thread(s) per MPI task +# + +variable T_depart equal 300 + +variable dt equal 0.0002 + +variable a equal 4.5937 +variable c equal 2.9587 +variable ca equal ${c}/${a} +variable ca equal 2.9587/${a} +variable ca equal 2.9587/4.5937 + +variable nx equal 6 +variable ny equal 6 +variable nz equal 11 + +variable bx equal ${a}*${nx} +variable bx equal 4.5937*${nx} +variable bx equal 4.5937*6 +variable by equal ${a}*${ny} +variable by equal 4.5937*${ny} +variable by equal 4.5937*6 +variable bz equal ${c}*${nz} +variable bz equal 2.9587*${nz} +variable bz equal 2.9587*11 +# ======================================================================= + +units metal +atom_style atomic +dimension 3 +boundary p p p + + +lattice sc 1.0 +Lattice spacing in x,y,z = 1 1 1 +region box_vide prism 0 ${bx} 0 ${by} 0 ${bz} 0.0 0.0 0.0 +region box_vide prism 0 27.5622 0 ${by} 0 ${bz} 0.0 0.0 0.0 +region box_vide prism 0 27.5622 0 27.5622 0 ${bz} 0.0 0.0 0.0 +region box_vide prism 0 27.5622 0 27.5622 0 32.5457 0.0 0.0 0.0 +create_box 2 box_vide +Created triclinic box = (0 0 0) to (27.5622 27.5622 32.5457) with tilt (0 0 0) + 1 by 1 by 1 MPI processor grid + +#lattice sc 1.0 +#region box_TiO2 block 0 ${bx} 0 ${by} 0 ${bz} + +# titanium atoms +lattice custom ${a} origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.0 0.0 0.0 basis 0.5 0.5 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.0 0.0 0.0 basis 0.5 0.5 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 0.644077758669482 basis 0.0 0.0 0.0 basis 0.5 0.5 0.5 +Lattice spacing in x,y,z = 4.5937 4.5937 2.9587 + +create_atoms 2 region box_vide +Created 792 atoms + +# Oxygen atoms +lattice custom ${a} origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.30478 0.30478 0.0 basis 0.69522 0.69522 0.0 basis 0.19522 0.80478 0.5 basis 0.80478 0.19522 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.30478 0.30478 0.0 basis 0.69522 0.69522 0.0 basis 0.19522 0.80478 0.5 basis 0.80478 0.19522 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 0.644077758669482 basis 0.30478 0.30478 0.0 basis 0.69522 0.69522 0.0 basis 0.19522 0.80478 0.5 basis 0.80478 0.19522 0.5 +Lattice spacing in x,y,z = 4.5937 4.5937 2.9587 + +create_atoms 1 region box_vide +Created 1584 atoms + + +mass 1 16.00 +group Oxy type 1 +1584 atoms in group Oxy + +mass 2 47.867 +group Ti type 2 +792 atoms in group Ti + +velocity all create ${T_depart} 277387 +velocity all create 300 277387 + +pair_style meam/spline +pair_coeff * * TiO.meam.spline O Ti +Reading potential file TiO.meam.spline with DATE: 2016-06-05 + +neighbor 0.5 bin +neigh_modify every 2 delay 0 check yes + +timestep ${dt} +timestep 0.0002 + +thermo_style custom step temp press pe ke etotal lx ly lz vol +thermo 10 + + +#dump 5 all custom 500 boxAlpha_alumina.lammpstrj id type q x y z + +fix 3 all nve +run 100 +Neighbor list info ... + update every 2 steps, delay 0 steps, check yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6 + ghost atom cutoff = 6 + binsize = 3, bins = 10 10 11 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam/spline, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam/spline, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 5.146 | 5.146 | 5.146 Mbytes +Step Temp Press PotEng KinEng TotEng Lx Ly Lz Volume + 0 300 22403.656 -14374.073 92.097853 -14281.975 27.5622 27.5622 32.5457 24724.15 + 10 301.41345 23612.297 -14374.507 92.531772 -14281.975 27.5622 27.5622 32.5457 24724.15 + 20 305.11674 25127.832 -14375.643 93.668657 -14281.974 27.5622 27.5622 32.5457 24724.15 + 30 313.28903 26655.89 -14378.151 96.17749 -14281.974 27.5622 27.5622 32.5457 24724.15 + 40 328.94567 26999.049 -14382.957 100.98397 -14281.974 27.5622 27.5622 32.5457 24724.15 + 50 354.05827 23023.294 -14390.667 108.69336 -14281.974 27.5622 27.5622 32.5457 24724.15 + 60 390.48404 13594.655 -14401.849 119.87581 -14281.973 27.5622 27.5622 32.5457 24724.15 + 70 442.69928 151.15709 -14417.877 135.90551 -14281.972 27.5622 27.5622 32.5457 24724.15 + 80 516.89551 -14984.124 -14440.654 158.68322 -14281.971 27.5622 27.5622 32.5457 24724.15 + 90 618.22135 -29948.066 -14471.76 189.78953 -14281.971 27.5622 27.5622 32.5457 24724.15 + 100 747.6193 -41964.291 -14511.487 229.51378 -14281.973 27.5622 27.5622 32.5457 24724.15 +Loop time of 38.7948 on 1 procs for 100 steps with 2376 atoms + +Performance: 0.045 ns/day, 538.817 hours/ns, 2.578 timesteps/s +99.7% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 38.774 | 38.774 | 38.774 | 0.0 | 99.95 +Neigh | 0.010751 | 0.010751 | 0.010751 | 0.0 | 0.03 +Comm | 0.0039313 | 0.0039313 | 0.0039313 | 0.0 | 0.01 +Output | 0.00048804 | 0.00048804 | 0.00048804 | 0.0 | 0.00 +Modify | 0.0039241 | 0.0039241 | 0.0039241 | 0.0 | 0.01 +Other | | 0.001809 | | | 0.00 + +Nlocal: 2376 ave 2376 max 2376 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 4479 ave 4479 max 4479 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 106396 ave 106396 max 106396 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 212792 ave 212792 max 212792 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 212792 +Ave neighs/atom = 89.5589 +Neighbor list builds = 1 +Dangerous builds = 0 + +unfix 3 +fix 1 all box/relax tri 0.0 vmax 0.001 +minimize 1.0e-3 1.0e-5 1000 10000 +WARNING: Resetting reneighboring criteria during minimization (../min.cpp:168) +Per MPI rank memory allocation (min/avg/max) = 6.271 | 6.271 | 6.271 Mbytes +Step Temp Press PotEng KinEng TotEng Lx Ly Lz Volume + 100 747.6193 -41964.291 -14511.487 229.51378 -14281.973 27.5622 27.5622 32.5457 24724.15 + 101 747.6193 -39284.65 -14517.424 229.51378 -14287.91 27.569615 27.569695 32.513154 24712.789 +Loop time of 0.814693 on 1 procs for 1 steps with 2376 atoms + +99.8% CPU use with 1 MPI tasks x 1 OpenMP threads + +Minimization stats: + Stopping criterion = energy tolerance + Energy initial, next-to-last, final = + -14511.4866189 -14511.4866189 -14517.4235162 + Force two-norm initial, final = 5602.25 5486.97 + Force max component initial, final = 5232.05 5109.43 + Final line search alpha, max atom move = 1.9113e-07 0.000976563 + Iterations, force evaluations = 1 1 + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.81429 | 0.81429 | 0.81429 | 0.0 | 99.95 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 6.485e-05 | 6.485e-05 | 6.485e-05 | 0.0 | 0.01 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 0.0003347 | | | 0.04 + +Nlocal: 2376 ave 2376 max 2376 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 4449 ave 4449 max 4449 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 105639 ave 105639 max 105639 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 211278 ave 211278 max 211278 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 211278 +Ave neighs/atom = 88.9217 +Neighbor list builds = 0 +Dangerous builds = 0 + +unfix 1 +reset_timestep 0 +thermo 50 +fix 3 all npt temp 300 300 0.1 aniso 1.0 1.0 1.0 +run 500 +Per MPI rank memory allocation (min/avg/max) = 5.162 | 5.162 | 5.162 Mbytes +Step Temp Press PotEng KinEng TotEng Lx Ly Lz Volume + 0 747.6193 -39284.65 -14517.424 229.51378 -14287.91 27.569615 27.569695 32.513154 24712.789 + 50 1155.2849 30650.319 -14678.807 354.6642 -14324.143 27.608688 27.60914 32.375311 24678.15 + 100 790.03926 99869.991 -14678.858 242.5364 -14436.322 27.777994 27.77799 32.017001 24704.857 + 150 938.86463 -21488.442 -14803.782 288.22472 -14515.557 27.996584 27.995139 31.67008 24822.003 + 200 420.11331 -790.80799 -14671.687 128.97178 -14542.715 28.126911 28.125909 31.431033 24864.93 + 250 352.18149 -3244.2491 -14665.007 108.1172 -14556.889 28.222686 28.223673 31.238649 24883.078 + 300 622.91245 3657.7097 -14758.201 191.22967 -14566.972 28.301771 28.30503 31.07216 24891.363 + 350 888.25374 26274.358 -14852.568 272.68754 -14579.881 28.370312 28.375107 30.937051 24904.656 + 400 735.44163 63109.066 -14823.872 225.77532 -14598.097 28.446905 28.45227 30.838015 24959.642 + 450 804.81905 6221.0364 -14861.113 247.07369 -14614.039 28.543942 28.548719 30.775793 25078.977 + 500 628.19106 -33912.026 -14814.726 192.85016 -14621.876 28.611997 28.615169 30.74081 25168.642 +Loop time of 176.167 on 1 procs for 500 steps with 2376 atoms + +Performance: 0.049 ns/day, 489.353 hours/ns, 2.838 timesteps/s +99.8% CPU use with 1 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 175.9 | 175.9 | 175.9 | 0.0 | 99.85 +Neigh | 0.17043 | 0.17043 | 0.17043 | 0.0 | 0.10 +Comm | 0.018243 | 0.018243 | 0.018243 | 0.0 | 0.01 +Output | 0.00040984 | 0.00040984 | 0.00040984 | 0.0 | 0.00 +Modify | 0.067142 | 0.067142 | 0.067142 | 0.0 | 0.04 +Other | | 0.00828 | | | 0.00 + +Nlocal: 2376 ave 2376 max 2376 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Nghost: 4358 ave 4358 max 4358 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +Neighs: 102634 ave 102634 max 102634 min +Histogram: 1 0 0 0 0 0 0 0 0 0 +FullNghs: 205268 ave 205268 max 205268 min +Histogram: 1 0 0 0 0 0 0 0 0 0 + +Total # of neighbors = 205268 +Ave neighs/atom = 86.3923 +Neighbor list builds = 16 +Dangerous builds = 0 + +Total wall time: 0:03:37 diff --git a/examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.4 b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.4 new file mode 100644 index 0000000000..6c2c949acb --- /dev/null +++ b/examples/USER/misc/meam_spline/log.4May2017.meam-spline.TiO2.g++.4 @@ -0,0 +1,248 @@ +LAMMPS (13 Apr 2017) + using 1 OpenMP thread(s) per MPI task +# + +variable T_depart equal 300 + +variable dt equal 0.0002 + +variable a equal 4.5937 +variable c equal 2.9587 +variable ca equal ${c}/${a} +variable ca equal 2.9587/${a} +variable ca equal 2.9587/4.5937 + +variable nx equal 6 +variable ny equal 6 +variable nz equal 11 + +variable bx equal ${a}*${nx} +variable bx equal 4.5937*${nx} +variable bx equal 4.5937*6 +variable by equal ${a}*${ny} +variable by equal 4.5937*${ny} +variable by equal 4.5937*6 +variable bz equal ${c}*${nz} +variable bz equal 2.9587*${nz} +variable bz equal 2.9587*11 +# ======================================================================= + +units metal +atom_style atomic +dimension 3 +boundary p p p + + +lattice sc 1.0 +Lattice spacing in x,y,z = 1 1 1 +region box_vide prism 0 ${bx} 0 ${by} 0 ${bz} 0.0 0.0 0.0 +region box_vide prism 0 27.5622 0 ${by} 0 ${bz} 0.0 0.0 0.0 +region box_vide prism 0 27.5622 0 27.5622 0 ${bz} 0.0 0.0 0.0 +region box_vide prism 0 27.5622 0 27.5622 0 32.5457 0.0 0.0 0.0 +create_box 2 box_vide +Created triclinic box = (0 0 0) to (27.5622 27.5622 32.5457) with tilt (0 0 0) + 1 by 2 by 2 MPI processor grid + +#lattice sc 1.0 +#region box_TiO2 block 0 ${bx} 0 ${by} 0 ${bz} + +# titanium atoms +lattice custom ${a} origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.0 0.0 0.0 basis 0.5 0.5 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.0 0.0 0.0 basis 0.5 0.5 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 0.644077758669482 basis 0.0 0.0 0.0 basis 0.5 0.5 0.5 +Lattice spacing in x,y,z = 4.5937 4.5937 2.9587 + +create_atoms 2 region box_vide +Created 792 atoms + +# Oxygen atoms +lattice custom ${a} origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.30478 0.30478 0.0 basis 0.69522 0.69522 0.0 basis 0.19522 0.80478 0.5 basis 0.80478 0.19522 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 ${ca} basis 0.30478 0.30478 0.0 basis 0.69522 0.69522 0.0 basis 0.19522 0.80478 0.5 basis 0.80478 0.19522 0.5 +lattice custom 4.5937 origin 0.0 0.0 0.0 orient x 1 0 0 orient y 0 1 0 orient z 0 0 1 a1 1.0 0.0 0.0 a2 0.0 1.0 0.0 a3 0.0 0.0 0.644077758669482 basis 0.30478 0.30478 0.0 basis 0.69522 0.69522 0.0 basis 0.19522 0.80478 0.5 basis 0.80478 0.19522 0.5 +Lattice spacing in x,y,z = 4.5937 4.5937 2.9587 + +create_atoms 1 region box_vide +Created 1584 atoms + + +mass 1 16.00 +group Oxy type 1 +1584 atoms in group Oxy + +mass 2 47.867 +group Ti type 2 +792 atoms in group Ti + +velocity all create ${T_depart} 277387 +velocity all create 300 277387 + +pair_style meam/spline +pair_coeff * * TiO.meam.spline O Ti +Reading potential file TiO.meam.spline with DATE: 2016-06-05 + +neighbor 0.5 bin +neigh_modify every 2 delay 0 check yes + +timestep ${dt} +timestep 0.0002 + +thermo_style custom step temp press pe ke etotal lx ly lz vol +thermo 10 + + +#dump 5 all custom 500 boxAlpha_alumina.lammpstrj id type q x y z + +fix 3 all nve +run 100 +Neighbor list info ... + update every 2 steps, delay 0 steps, check yes + max neighbors/atom: 2000, page size: 100000 + master list distance cutoff = 6 + ghost atom cutoff = 6 + binsize = 3, bins = 10 10 11 + 2 neighbor lists, perpetual/occasional/extra = 2 0 0 + (1) pair meam/spline, perpetual + attributes: full, newton on + pair build: full/bin/atomonly + stencil: full/bin/3d + bin: standard + (2) pair meam/spline, perpetual, half/full from (1) + attributes: half, newton on + pair build: halffull/newton + stencil: none + bin: none +Per MPI rank memory allocation (min/avg/max) = 3.922 | 3.922 | 3.922 Mbytes +Step Temp Press PotEng KinEng TotEng Lx Ly Lz Volume + 0 300 22403.656 -14374.073 92.097853 -14281.975 27.5622 27.5622 32.5457 24724.15 + 10 301.16725 23582.084 -14374.431 92.456192 -14281.975 27.5622 27.5622 32.5457 24724.15 + 20 304.58237 25059.749 -14375.479 93.504609 -14281.974 27.5622 27.5622 32.5457 24724.15 + 30 312.41477 26504.358 -14377.883 95.9091 -14281.974 27.5622 27.5622 32.5457 24724.15 + 40 327.67099 26687.057 -14382.566 100.59265 -14281.974 27.5622 27.5622 32.5457 24724.15 + 50 352.32125 22677.292 -14390.134 108.1601 -14281.974 27.5622 27.5622 32.5457 24724.15 + 60 388.40592 12472.705 -14401.211 119.23784 -14281.973 27.5622 27.5622 32.5457 24724.15 + 70 439.97199 -1520.4694 -14417.04 135.06825 -14281.972 27.5622 27.5622 32.5457 24724.15 + 80 513.34361 -16733.316 -14439.564 157.59282 -14281.971 27.5622 27.5622 32.5457 24724.15 + 90 613.3542 -31099.591 -14470.267 188.29535 -14281.971 27.5622 27.5622 32.5457 24724.15 + 100 741.02836 -42358.226 -14509.464 227.4904 -14281.973 27.5622 27.5622 32.5457 24724.15 +Loop time of 8.92317 on 4 procs for 100 steps with 2376 atoms + +Performance: 0.194 ns/day, 123.933 hours/ns, 11.207 timesteps/s +99.5% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 8.8912 | 8.9 | 8.9064 | 0.2 | 99.74 +Neigh | 0.0027034 | 0.0028808 | 0.0032032 | 0.4 | 0.03 +Comm | 0.010964 | 0.017648 | 0.026568 | 5.0 | 0.20 +Output | 0.00037575 | 0.00047809 | 0.00053835 | 0.0 | 0.01 +Modify | 0.00099134 | 0.001001 | 0.0010085 | 0.0 | 0.01 +Other | | 0.001162 | | | 0.01 + +Nlocal: 594 ave 599 max 589 min +Histogram: 1 0 0 0 0 2 0 0 0 1 +Nghost: 2290.25 ave 2296 max 2282 min +Histogram: 1 0 0 0 1 0 0 0 1 1 +Neighs: 26671.5 ave 26934 max 26495 min +Histogram: 1 0 0 2 0 0 0 0 0 1 +FullNghs: 53343 ave 53828 max 52922 min +Histogram: 1 0 0 0 2 0 0 0 0 1 + +Total # of neighbors = 213372 +Ave neighs/atom = 89.803 +Neighbor list builds = 1 +Dangerous builds = 0 + +unfix 3 +fix 1 all box/relax tri 0.0 vmax 0.001 +minimize 1.0e-3 1.0e-5 1000 10000 +WARNING: Resetting reneighboring criteria during minimization (../min.cpp:168) +Per MPI rank memory allocation (min/avg/max) = 5.047 | 5.047 | 5.047 Mbytes +Step Temp Press PotEng KinEng TotEng Lx Ly Lz Volume + 100 741.02836 -42358.226 -14509.464 227.4904 -14281.973 27.5622 27.5622 32.5457 24724.15 + 101 741.02836 -39686.588 -14515.398 227.4904 -14287.907 27.569587 27.569656 32.513154 24712.729 +Loop time of 0.193516 on 4 procs for 1 steps with 2376 atoms + +99.5% CPU use with 4 MPI tasks x 1 OpenMP threads + +Minimization stats: + Stopping criterion = energy tolerance + Energy initial, next-to-last, final = + -14509.46351 -14509.46351 -14515.3978891 + Force two-norm initial, final = 5602.69 5487.77 + Force max component initial, final = 5235.27 5113.06 + Final line search alpha, max atom move = 1.91012e-07 0.000976657 + Iterations, force evaluations = 1 1 + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 0.19287 | 0.19299 | 0.19318 | 0.0 | 99.73 +Neigh | 0 | 0 | 0 | 0.0 | 0.00 +Comm | 0.00014043 | 0.00033247 | 0.00045896 | 0.0 | 0.17 +Output | 0 | 0 | 0 | 0.0 | 0.00 +Modify | 0 | 0 | 0 | 0.0 | 0.00 +Other | | 0.0001886 | | | 0.10 + +Nlocal: 594 ave 601 max 586 min +Histogram: 1 0 0 0 0 1 1 0 0 1 +Nghost: 2263.25 ave 2271 max 2251 min +Histogram: 1 0 0 0 0 0 1 0 1 1 +Neighs: 26425.8 ave 26807 max 26121 min +Histogram: 1 0 0 1 1 0 0 0 0 1 +FullNghs: 52851.5 ave 53580 max 52175 min +Histogram: 1 0 0 0 2 0 0 0 0 1 + +Total # of neighbors = 211406 +Ave neighs/atom = 88.9756 +Neighbor list builds = 0 +Dangerous builds = 0 + +unfix 1 +reset_timestep 0 +thermo 50 +fix 3 all npt temp 300 300 0.1 aniso 1.0 1.0 1.0 +run 500 +Per MPI rank memory allocation (min/avg/max) = 3.937 | 3.937 | 3.937 Mbytes +Step Temp Press PotEng KinEng TotEng Lx Ly Lz Volume + 0 741.02836 -39686.588 -14515.398 227.4904 -14287.907 27.569587 27.569656 32.513154 24712.729 + 50 1157.347 29332.549 -14679.321 355.29725 -14324.024 27.60903 27.609325 32.375509 24678.772 + 100 777.55858 101883.12 -14674.854 238.70492 -14436.149 27.778518 27.777373 32.017262 24704.976 + 150 945.49014 -18305.383 -14806.687 290.25871 -14516.428 27.998313 27.99535 31.670225 24823.838 + 200 427.46608 -4045.0095 -14674.887 131.22903 -14543.658 28.130283 28.127147 31.431578 24869.438 + 250 362.82166 -7283.1332 -14669.07 111.38365 -14557.687 28.225232 28.222707 31.238451 24884.314 + 300 626.2858 7228.0309 -14760.128 192.26526 -14567.862 28.302384 28.299949 31.070038 24885.734 + 350 859.84293 30084.735 -14845.064 263.96563 -14581.099 28.372349 28.369334 30.934424 24899.261 + 400 755.26136 54745.408 -14830.701 231.85983 -14598.842 28.450301 28.448361 30.836159 24957.691 + 450 802.52344 5690.2863 -14860.193 246.36895 -14613.824 28.542311 28.541672 30.773339 25069.354 + 500 631.84734 -31473.795 -14816.101 193.97261 -14622.128 28.605857 28.605891 30.737955 25152.746 +Loop time of 39.7881 on 4 procs for 500 steps with 2376 atoms + +Performance: 0.217 ns/day, 110.522 hours/ns, 12.567 timesteps/s +99.4% CPU use with 4 MPI tasks x 1 OpenMP threads + +MPI task timing breakdown: +Section | min time | avg time | max time |%varavg| %total +--------------------------------------------------------------- +Pair | 39.617 | 39.633 | 39.653 | 0.2 | 99.61 +Neigh | 0.043624 | 0.046792 | 0.051708 | 1.4 | 0.12 +Comm | 0.05215 | 0.072616 | 0.092142 | 5.6 | 0.18 +Output | 0.00042915 | 0.00045079 | 0.00051546 | 0.0 | 0.00 +Modify | 0.029836 | 0.030341 | 0.03094 | 0.2 | 0.08 +Other | | 0.004489 | | | 0.01 + +Nlocal: 594 ave 606 max 582 min +Histogram: 1 0 0 0 1 1 0 0 0 1 +Nghost: 2226 ave 2238 max 2214 min +Histogram: 1 0 0 0 1 1 0 0 0 1 +Neighs: 25652.8 ave 26129 max 25153 min +Histogram: 1 0 0 0 1 1 0 0 0 1 +FullNghs: 51305.5 ave 52398 max 50251 min +Histogram: 1 0 0 0 1 1 0 0 0 1 + +Total # of neighbors = 205222 +Ave neighs/atom = 86.3729 +Neighbor list builds = 16 +Dangerous builds = 0 + +Total wall time: 0:00:49