updates "add eco df"
We think we followed all your requests/advice/suggestions (thanks!). We were unable to compile the current master (!) on Ubuntu and MacOS unless we added -std=c++11 to the Makefile(s) compiler flags. Note that this is NOT related to this pull request / the ECO Force. With this compiler flag, the current master works well with the fix_orient_eco (now renamed). The fix has been moved to USER-MISC (but we hope to get it to MISC later). We can't "make style_check ", but we have added our command to commands_fix.rst. We don't know GitHub well enough, so we don't know how to make sure that the PR #2122 was already included in the master, which we downloaded today.
This commit is contained in:
@ -147,6 +147,7 @@ OPT.
|
|||||||
* :doc:`oneway <fix_oneway>`
|
* :doc:`oneway <fix_oneway>`
|
||||||
* :doc:`orient/bcc <fix_orient>`
|
* :doc:`orient/bcc <fix_orient>`
|
||||||
* :doc:`orient/fcc <fix_orient>`
|
* :doc:`orient/fcc <fix_orient>`
|
||||||
|
* :doc:`orient/eco <fix_orient_eco>`
|
||||||
* :doc:`phonon <fix_phonon>`
|
* :doc:`phonon <fix_phonon>`
|
||||||
* :doc:`pimd <fix_pimd>`
|
* :doc:`pimd <fix_pimd>`
|
||||||
* :doc:`planeforce <fix_planeforce>`
|
* :doc:`planeforce <fix_planeforce>`
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
.. index:: fix eco/force
|
.. index:: fix orient/eco
|
||||||
|
|
||||||
fix eco/force command
|
fix orient/eco command
|
||||||
=====================
|
======================
|
||||||
|
|
||||||
|
|
||||||
.. parsed-literal::
|
.. parsed-literal::
|
||||||
|
|
||||||
fix ID group-ID eco/force u0 eta rcut file
|
fix ID group-ID orient/eco u0 eta rcut orientationsFile
|
||||||
|
|
||||||
|
|
||||||
* ID, group-ID are documented in fix command
|
* ID, group-ID are documented in fix command
|
||||||
* u0 = energy added to each atom (energy units)
|
* u0 = energy added to each atom (energy units)
|
||||||
* eta = cutoff value (usually 0.25)
|
* eta = cutoff value (usually 0.25)
|
||||||
* rcut = cutoff radius for orientation parameter calculation
|
* rcut = cutoff radius for orientation parameter calculation
|
||||||
* file = file that specifies orientation of each grain
|
* orientationsFile = file that specifies orientation of each grain
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
""""""""
|
""""""""
|
||||||
|
|
||||||
.. code-block:: LAMMPS
|
.. code-block:: LAMMPS
|
||||||
|
|
||||||
fix gb all eco/force 0.08 0.25 3.524 sigma5.ori
|
fix gb all orient/eco 0.08 0.25 3.524 sigma5.ori
|
||||||
|
|
||||||
|
|
||||||
Description
|
Description
|
||||||
@ -76,36 +76,37 @@ depends on the surrounding of this atom. An atom far from the grain boundary doe
|
|||||||
experience a synthetic force as its surrounding is that of an oriented single crystal
|
experience a synthetic force as its surrounding is that of an oriented single crystal
|
||||||
and thermal fluctuations are masked by the parameter eta. Near the grain boundary
|
and thermal fluctuations are masked by the parameter eta. Near the grain boundary
|
||||||
however, the gradient is nonzero and synthetic force terms are computed.
|
however, the gradient is nonzero and synthetic force terms are computed.
|
||||||
The orientation file specifies the perfect oriented crystal basis vectors for the
|
The orientationsFile specifies the perfect oriented crystal basis vectors for the
|
||||||
two adjoining crystals. The first three lines for the energetically penalized and the
|
two adjoining crystals. The first three lines (line=row vector) for the energetically penalized and the
|
||||||
last three lines for the energetically favored grain assuming u0 is positive. For
|
last three lines for the energetically favored grain assuming u0 is positive. For
|
||||||
negative u0 this is reversed. With the rcut parameter, the size of the region around
|
negative u0, this is reversed. With the rcut parameter, the size of the region around
|
||||||
each atom which is used in the order parameter computation is defined. It should at
|
each atom which is used in the order parameter computation is defined. rcut must be
|
||||||
|
smaller than the interaction range of the MD potential. It should at
|
||||||
least include the nearest neighbor shell. For high temperatures or low angle
|
least include the nearest neighbor shell. For high temperatures or low angle
|
||||||
grain boundaries, it might be beneficial to increase rcut in order to get a more
|
grain boundaries, it might be beneficial to increase rcut in order to get a more
|
||||||
precise identification of the atoms surrounding. However, computation time will
|
precise identification of the atoms surrounding. However, computation time will
|
||||||
increase as more atoms considered in the order parameter and force computation.
|
increase as more atoms are considered in the order parameter and force computation.
|
||||||
It is also worth noting that the cutoff radius must not exceed the communication
|
It is also worth noting that the cutoff radius must not exceed the communication
|
||||||
distance for ghost atoms in LAMMPS. Currently however, the method stores results
|
distance for ghost atoms in LAMMPS. Currently however, the method stores results
|
||||||
for order parameter and force computations in statically allocated arrays to
|
for order parameter and force computations in statically allocated arrays to
|
||||||
increase efficiency such that the user is limited to 24 nearest neighbors.
|
increase efficiency such that the user is limited to 24 nearest neighbors.
|
||||||
This is more than enough in most applications. With file, the input file for
|
This is more than enough in most applications. With orientationsFile, the
|
||||||
the 6 oriented crystal basis vectors is specified. Each line of the input file
|
6 oriented crystal basis vectors is specified. Each line of the input file
|
||||||
contains the three components of a primitive lattice vector oriented according to
|
contains the three components of a primitive lattice vector oriented according to
|
||||||
the grain orientation in the simulation box. The first (last) three lines correspond
|
the grain orientation in the simulation box. The first (last) three lines correspond
|
||||||
to the primitive lattice vectors of the first (second) grain. An example for
|
to the primitive lattice vectors of the first (second) grain. An example for
|
||||||
a :math:`\Sigma\langle001\rangle` misorientation is given at the end.
|
a :math:`\Sigma\langle001\rangle` misorientation is given at the end.
|
||||||
|
|
||||||
If no synthetic energy difference between the grains is created, u0=0, the
|
If no synthetic energy difference between the grains is created, u0=0, the
|
||||||
force computation is omitted. In this case, the order parameter of the
|
force computation is omitted. In this case, still, the order parameter of the
|
||||||
driving force can be used to track the grain boundary motion throughout the
|
driving force is computed and can be used to track the grain boundary motion throughout the
|
||||||
simulation.
|
simulation.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Restart, fix_modify, output, run start/stop, minimize info:**
|
**Restart, fix_modify, output, run start/stop, minimize info:**
|
||||||
|
|
||||||
No information about this fix is written to :doc: `binary restart files`.
|
No information about this fix is written to :doc: `binary restart files <restart>`.
|
||||||
|
|
||||||
The :doc:`fix_modify <fix_modify>` *energy* option is supported by this fix to
|
The :doc:`fix_modify <fix_modify>` *energy* option is supported by this fix to
|
||||||
add the potential energy of atom interactions with the grain boundary
|
add the potential energy of atom interactions with the grain boundary
|
||||||
@ -113,7 +114,7 @@ driving force to the system's potential energy as part of thermodynamic output.
|
|||||||
The total sum of added synthetic potential energy is computed and can be accessed
|
The total sum of added synthetic potential energy is computed and can be accessed
|
||||||
by various output options. The order parameter as well as the thermally masked
|
by various output options. The order parameter as well as the thermally masked
|
||||||
output parameter are stored in per-atom arrays and can also be accessed by various
|
output parameter are stored in per-atom arrays and can also be accessed by various
|
||||||
output commands.
|
:doc:`output commands <Howto_output>`.
|
||||||
|
|
||||||
No parameter of this fix can be used with the start/stop keywords of the run command. This fix is
|
No parameter of this fix can be used with the start/stop keywords of the run command. This fix is
|
||||||
not invoked during energy minimization.
|
not invoked during energy minimization.
|
||||||
@ -123,7 +124,7 @@ not invoked during energy minimization.
|
|||||||
Restrictions
|
Restrictions
|
||||||
""""""""""""
|
""""""""""""
|
||||||
|
|
||||||
This fix is part of the MISC package. It is only enabled if LAMMPS was
|
This fix is part of the USER-MISC package. It is only enabled if LAMMPS was
|
||||||
built with that package. See the :doc:`Build package <Build_package>` doc page for more info.
|
built with that package. See the :doc:`Build package <Build_package>` doc page for more info.
|
||||||
|
|
||||||
|
|
||||||
@ -133,6 +134,8 @@ Related commands
|
|||||||
|
|
||||||
:doc:`fix_modify <fix_modify>`
|
:doc:`fix_modify <fix_modify>`
|
||||||
|
|
||||||
|
:doc:`fix_orient <fix_orient>`
|
||||||
|
|
||||||
**Default:** none
|
**Default:** none
|
||||||
|
|
||||||
----------
|
----------
|
||||||
17
examples/USER/misc/orient_eco/orient_eco.in
Executable file
17
examples/USER/misc/orient_eco/orient_eco.in
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
log log.orient_eco
|
||||||
|
dimension 3
|
||||||
|
boundary p p p
|
||||||
|
units metal
|
||||||
|
atom_style atomic
|
||||||
|
read_data examples/USER/misc/orient_eco/sigma5.lammps
|
||||||
|
pair_style eam
|
||||||
|
pair_coeff * * potentials/Ni_u3.eam
|
||||||
|
timestep 0.001
|
||||||
|
fix integrator all npt temp 750 750 0.1 iso 0 0 0.1
|
||||||
|
fix eco all orient/eco 0.08 0.25 3.6 examples/USER/misc/orient_eco/sigma5.ori
|
||||||
|
thermo 100
|
||||||
|
thermo_style custom step temp etotal press vol f_eco
|
||||||
|
velocity all create 750 1
|
||||||
|
dump save all custom 100 orient_eco.dump xs ys zs f_eco[1] f_eco[2]
|
||||||
|
dump_modify save sort id
|
||||||
|
run 1000
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,17 +0,0 @@
|
|||||||
log eam.log
|
|
||||||
dimension 3
|
|
||||||
boundary p p p
|
|
||||||
units metal
|
|
||||||
atom_style atomic
|
|
||||||
lattice fcc 3.5
|
|
||||||
read_data examples/eco_force/sigma5.lammps
|
|
||||||
pair_style eam/fs
|
|
||||||
pair_coeff * * examples/eco_force/Ni.eam.fs Ni
|
|
||||||
timestep 0.001
|
|
||||||
thermo 100
|
|
||||||
fix integrator all npt temp 750 750 0.1 iso 0 0 0.1
|
|
||||||
fix eco all eco/force 0.08 0.25 3.6 examples/eco_force/sigma5.ori
|
|
||||||
velocity all create 750 1
|
|
||||||
dump save all custom 100 nidata_eam.dump xs ys zs f_eco[1] f_eco[2]
|
|
||||||
dump_modify save sort id
|
|
||||||
run 1000
|
|
||||||
@ -7,7 +7,7 @@ SHELL = /bin/sh
|
|||||||
# specify flags and libraries needed for your compiler
|
# specify flags and libraries needed for your compiler
|
||||||
|
|
||||||
CC = mpicxx
|
CC = mpicxx
|
||||||
CCFLAGS = -g -O3
|
CCFLAGS = -g -O3 -std=c++11
|
||||||
SHFLAGS = -fPIC
|
SHFLAGS = -fPIC
|
||||||
DEPFLAGS = -M
|
DEPFLAGS = -M
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ SHELL = /bin/sh
|
|||||||
# specify flags and libraries needed for your compiler
|
# specify flags and libraries needed for your compiler
|
||||||
|
|
||||||
CC = g++
|
CC = g++
|
||||||
CCFLAGS = -g -O3
|
CCFLAGS = -g -O3 -std=c++11
|
||||||
SHFLAGS = -fPIC
|
SHFLAGS = -fPIC
|
||||||
DEPFLAGS = -M
|
DEPFLAGS = -M
|
||||||
|
|
||||||
|
|||||||
657
src/USER-MISC/fix_orient_eco.cpp
Executable file
657
src/USER-MISC/fix_orient_eco.cpp
Executable file
@ -0,0 +1,657 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratdir_veces
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Contributing authors: Adrian A. Schratt and Volker Mohles (ICAMS)
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#include "fix_orient_eco.h"
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include "atom.h"
|
||||||
|
#include "citeme.h"
|
||||||
|
#include "comm.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "force.h"
|
||||||
|
#include "math_const.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "neigh_list.h"
|
||||||
|
#include "neigh_request.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "pair.h"
|
||||||
|
#include "respa.h"
|
||||||
|
#include "update.h"
|
||||||
|
|
||||||
|
using namespace LAMMPS_NS;
|
||||||
|
using namespace FixConst;
|
||||||
|
using namespace MathConst;
|
||||||
|
|
||||||
|
static const char cite_fix_orient_eco[] =
|
||||||
|
"fix orient/eco command:\n\n"
|
||||||
|
"@Article{Schratt20,\n"
|
||||||
|
" author = {A. A. Schratt, V. Mohles},\n"
|
||||||
|
" title = {Efficient calculation of the ECO driving force for atomistic simulations of grain boundary motion},\n"
|
||||||
|
" journal = {Computational Materials Science},\n"
|
||||||
|
" volume = {182},\n"
|
||||||
|
" year = {2020},\n"
|
||||||
|
" pages = {109774},\n"
|
||||||
|
" doi = {j.commatsci.2020.109774},\n"
|
||||||
|
" url = {https://doi.org/10.1016/j.commatsci.2020.109774}\n"
|
||||||
|
"}\n\n";
|
||||||
|
|
||||||
|
#define FIX_ORIENT_ECO_MAX_NEIGH 24
|
||||||
|
|
||||||
|
struct FixOrientECO::Nbr {
|
||||||
|
public:
|
||||||
|
int n; // # of neighbors
|
||||||
|
tagint id[FIX_ORIENT_ECO_MAX_NEIGH]; // IDs of each neighbor
|
||||||
|
// if center atom is owned, these are local IDs
|
||||||
|
// if center atom is ghost, these are global IDs
|
||||||
|
double duchi; // potential derivative
|
||||||
|
double delta[FIX_ORIENT_ECO_MAX_NEIGH][3]; // difference vectors
|
||||||
|
double real_phi[2][3]; // real part of wave function
|
||||||
|
double imag_phi[2][3]; // imaginary part of wave function
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
FixOrientECO::FixOrientECO(LAMMPS *lmp, int narg, char **arg) :
|
||||||
|
Fix(lmp, narg, arg),
|
||||||
|
dir_filename(NULL), order(NULL), nbr(NULL), list(NULL)
|
||||||
|
{
|
||||||
|
if (lmp->citeme) lmp->citeme->add(cite_fix_orient_eco);
|
||||||
|
|
||||||
|
// get rank of this processor
|
||||||
|
MPI_Comm_rank(world, &me);
|
||||||
|
|
||||||
|
// check for illegal command
|
||||||
|
if (narg != 7) error->all(FLERR, "Illegal fix orient/eco command");
|
||||||
|
|
||||||
|
// set fix flags
|
||||||
|
scalar_flag = 1; // computes scalar
|
||||||
|
global_freq = 1; // values can be computed at every timestep
|
||||||
|
extscalar = 1; // scalar scales with # of atoms
|
||||||
|
peratom_flag = 1; // quantities are per atom quantities
|
||||||
|
size_peratom_cols = 2; // # of per atom quantities
|
||||||
|
peratom_freq = 1; //
|
||||||
|
|
||||||
|
// parse input parameters
|
||||||
|
u_0 = force->numeric(FLERR, arg[3]);
|
||||||
|
sign = (u_0 >= 0.0 ? 1 : -1);
|
||||||
|
eta = force->numeric(FLERR, arg[4]);
|
||||||
|
r_cut = force->numeric(FLERR, arg[5]);
|
||||||
|
|
||||||
|
// read reference orientations from file
|
||||||
|
// work on rank 0 only
|
||||||
|
int n = strlen(arg[6]) + 1;
|
||||||
|
dir_filename = new char[n];
|
||||||
|
strcpy(dir_filename, arg[6]);
|
||||||
|
if (me == 0) {
|
||||||
|
char line[IMGMAX];
|
||||||
|
char *result;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
FILE *infile = force->open_potential(dir_filename);
|
||||||
|
if (infile == NULL) error->one(FLERR, "Fix orient/eco file open failed");
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
result = fgets(line, IMGMAX, infile);
|
||||||
|
if (!result) error->one(FLERR, "Fix orient/eco file read failed");
|
||||||
|
count = sscanf(line, "%lg %lg %lg", &dir_vec[i][0], &dir_vec[i][1], &dir_vec[i][2]);
|
||||||
|
if (count != 3) error->one(FLERR, "Fix orient/eco file read failed");
|
||||||
|
}
|
||||||
|
fclose(infile);
|
||||||
|
|
||||||
|
// calculate reciprocal lattice vectors
|
||||||
|
get_reciprocal();
|
||||||
|
|
||||||
|
squared_cutoff = r_cut * r_cut;
|
||||||
|
inv_squared_cutoff = 1.0 / squared_cutoff;
|
||||||
|
half_u = 0.5 * u_0;
|
||||||
|
inv_eta = 1.0 / eta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initializations
|
||||||
|
MPI_Bcast(&dir_vec[0][0], 18, MPI_DOUBLE, 0, world); // communicate direct lattice vectors
|
||||||
|
MPI_Bcast(&reciprocal_vectors[0][0][0], 18, MPI_DOUBLE, 0, world); // communicate reciprocal vectors
|
||||||
|
MPI_Bcast(&squared_cutoff, 1, MPI_DOUBLE, 0, world); // communicate squared cutoff radius
|
||||||
|
MPI_Bcast(&inv_squared_cutoff, 1, MPI_DOUBLE, 0, world); // communicate inverse squared cutoff radius
|
||||||
|
MPI_Bcast(&half_u, 1, MPI_DOUBLE, 0, world); // communicate half potential energy
|
||||||
|
MPI_Bcast(&inv_eta, 1, MPI_DOUBLE, 0, world); // communicate inverse threshold
|
||||||
|
|
||||||
|
// set comm size needed by this Fix
|
||||||
|
comm_forward = 2 + 4 * FIX_ORIENT_ECO_MAX_NEIGH; // data of Nbr struct that needs to be communicated in any case
|
||||||
|
if (u_0 != 0) comm_forward += 12; // real_phi and imag_phi needed for force computation
|
||||||
|
|
||||||
|
added_energy = 0.0; // initial energy
|
||||||
|
|
||||||
|
nmax = atom->nmax;
|
||||||
|
nbr = (Nbr *) memory->smalloc(nmax * sizeof(Nbr), "orient/eco:nbr");
|
||||||
|
memory->create(order, nmax, 2, "orient/eco:order");
|
||||||
|
array_atom = order;
|
||||||
|
|
||||||
|
// zero the array since a variable may access it before first run
|
||||||
|
for (int i = 0; i < atom->nlocal; ++i) order[i][0] = order[i][1] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
FixOrientECO::~FixOrientECO() {
|
||||||
|
memory->destroy(order);
|
||||||
|
memory->sfree(nbr);
|
||||||
|
delete[] dir_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int FixOrientECO::setmask() {
|
||||||
|
int mask = 0;
|
||||||
|
mask |= POST_FORCE;
|
||||||
|
mask |= THERMO_ENERGY;
|
||||||
|
mask |= POST_FORCE_RESPA;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::init() {
|
||||||
|
// get this processors rank
|
||||||
|
MPI_Comm_rank(world, &me);
|
||||||
|
|
||||||
|
// compute normalization factor
|
||||||
|
if (me == 0) {
|
||||||
|
int neigh;
|
||||||
|
get_norm(neigh);
|
||||||
|
if (screen) {
|
||||||
|
fprintf(screen, " fix orient/eco: cutoff=%f norm_fac=%f neighbors=%i\n", r_cut, norm_fac, neigh);
|
||||||
|
}
|
||||||
|
if (logfile) {
|
||||||
|
fprintf(logfile, " fix orient/eco: cutoff=%f norm_fac=%f neighbors=%i\n", r_cut, norm_fac, neigh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inv_norm_fac = 1.0 / norm_fac;
|
||||||
|
|
||||||
|
// check parameters
|
||||||
|
if (r_cut > force->pair->cutforce) {
|
||||||
|
error->all(FLERR, "Cutoff radius used by fix orient/eco must be smaller than force cutoff");
|
||||||
|
}
|
||||||
|
|
||||||
|
// communicate normalization factor
|
||||||
|
MPI_Bcast(&norm_fac, 1, MPI_DOUBLE, 0, world);
|
||||||
|
MPI_Bcast(&inv_norm_fac, 1, MPI_DOUBLE, 0, world);
|
||||||
|
|
||||||
|
if (strstr(update->integrate_style, "respa")) {
|
||||||
|
ilevel_respa = ((Respa *) update->integrate)->nlevels - 1;
|
||||||
|
if (respa_level >= 0) ilevel_respa = MIN(respa_level, ilevel_respa);
|
||||||
|
}
|
||||||
|
|
||||||
|
// need a full neighbor list
|
||||||
|
// perpetual list, built whenever re-neighboring occurs
|
||||||
|
|
||||||
|
int irequest = neighbor->request(this, instance_me);
|
||||||
|
neighbor->requests[irequest]->pair = 0;
|
||||||
|
neighbor->requests[irequest]->fix = 1;
|
||||||
|
neighbor->requests[irequest]->half = 0;
|
||||||
|
neighbor->requests[irequest]->full = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::init_list(int id, NeighList *ptr) {
|
||||||
|
list = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::setup(int vflag) {
|
||||||
|
if (strstr(update->integrate_style, "verlet"))
|
||||||
|
post_force(vflag);
|
||||||
|
else {
|
||||||
|
((Respa *) update->integrate)->copy_flevel_f(ilevel_respa);
|
||||||
|
post_force_respa(vflag,ilevel_respa, 0);
|
||||||
|
((Respa *) update->integrate)->copy_f_flevel(ilevel_respa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::post_force(int vflag) {
|
||||||
|
// set local variables
|
||||||
|
int ii, i, jj, j; // loop variables and atom IDs
|
||||||
|
int k; // variable to loop over 3 reciprocal directions
|
||||||
|
int lambda; // variable to loop over 2 crystals
|
||||||
|
int dim; // variable to loop over 3 spatial components
|
||||||
|
int n; // stores current number of neighbors
|
||||||
|
double dx, dy, dz; // stores current interatomic vector
|
||||||
|
double squared_distance; // stores current squared distance
|
||||||
|
double chi; // stores current order parameter
|
||||||
|
double *delta; // pointer to current interatomic vector (POSSIBLY OMIT)
|
||||||
|
double weight; // stores current weight function
|
||||||
|
double scalar_product; // stores current scalar product
|
||||||
|
double omega; // phase of sine transition
|
||||||
|
double omega_pre = MY_PI2 * inv_eta; // prefactor for omega
|
||||||
|
double duchi_pre = half_u * MY_PI * inv_eta * inv_norm_fac; // prefactor for duchi
|
||||||
|
double sin_om; // stores the value of the sine transition
|
||||||
|
|
||||||
|
// initialize added energy at this step
|
||||||
|
added_energy = 0.0;
|
||||||
|
|
||||||
|
// set local pointers and neighbor lists
|
||||||
|
double **x = atom->x;
|
||||||
|
double **f = atom->f;
|
||||||
|
int *mask = atom->mask;
|
||||||
|
int nall = atom->nlocal + atom->nghost;
|
||||||
|
|
||||||
|
int inum = list->inum;
|
||||||
|
int jnum;
|
||||||
|
int *ilist = list->ilist;
|
||||||
|
int *jlist;
|
||||||
|
int *numneigh = list->numneigh;
|
||||||
|
int **firstneigh = list->firstneigh;
|
||||||
|
|
||||||
|
// insure nbr and order data structures are adequate size
|
||||||
|
if (nall > nmax) {
|
||||||
|
nmax = nall;
|
||||||
|
memory->destroy(nbr);
|
||||||
|
memory->destroy(order);
|
||||||
|
nbr = (Nbr *) memory->smalloc(nmax * sizeof(Nbr), "orient/eco:nbr");
|
||||||
|
memory->create(order, nmax, 2, "orient/eco:order");
|
||||||
|
array_atom = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop over owned atoms and build Nbr data structure of neighbors
|
||||||
|
// use full neighbor list
|
||||||
|
for (ii = 0; ii < inum; ++ii) {
|
||||||
|
i = ilist[ii];
|
||||||
|
jlist = firstneigh[i];
|
||||||
|
jnum = numneigh[i];
|
||||||
|
|
||||||
|
// loop over all neighbors of atom i
|
||||||
|
// for those within squared_cutoff, store id and delta vectors
|
||||||
|
n = 0;
|
||||||
|
for (jj = 0; jj < jnum; ++jj) {
|
||||||
|
j = jlist[jj];
|
||||||
|
j &= NEIGHMASK;
|
||||||
|
|
||||||
|
// vector difference
|
||||||
|
dx = x[i][0] - x[j][0];
|
||||||
|
dy = x[i][1] - x[j][1];
|
||||||
|
dz = x[i][2] - x[j][2];
|
||||||
|
squared_distance = dx * dx + dy * dy + dz * dz;
|
||||||
|
|
||||||
|
if (squared_distance < squared_cutoff) {
|
||||||
|
if (n >= FIX_ORIENT_ECO_MAX_NEIGH) {
|
||||||
|
error->one(FLERR, "Fix orient/eco maximal number of neighbors exceeded");
|
||||||
|
}
|
||||||
|
nbr[i].id[n] = static_cast<tagint> (j);
|
||||||
|
nbr[i].delta[n][0] = dx;
|
||||||
|
nbr[i].delta[n][1] = dy;
|
||||||
|
nbr[i].delta[n][2] = dz;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nbr[i].n = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop over owned atoms and compute order parameter
|
||||||
|
// use short neighbor lists
|
||||||
|
for (ii = 0; ii < inum; ++ii) {
|
||||||
|
i = ilist[ii];
|
||||||
|
|
||||||
|
// initializations
|
||||||
|
n = nbr[i].n;
|
||||||
|
chi = 0.0;
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
nbr[i].real_phi[0][k] = nbr[i].real_phi[1][k] = 0.0;
|
||||||
|
nbr[i].imag_phi[0][k] = nbr[i].imag_phi[1][k] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop over all neighbors of atom i
|
||||||
|
for (j = 0; j < n; ++j) {
|
||||||
|
delta = &nbr[i].delta[j][0];
|
||||||
|
squared_distance = (delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]) * inv_squared_cutoff;
|
||||||
|
weight = squared_distance * (squared_distance - 2.0) + 1.0;
|
||||||
|
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
for (lambda = 0; lambda < 2; ++lambda) {
|
||||||
|
scalar_product = reciprocal_vectors[lambda][k][0] * delta[0] + reciprocal_vectors[lambda][k][1] * delta[1] + reciprocal_vectors[lambda][k][2] * delta[2];
|
||||||
|
nbr[i].real_phi[lambda][k] += weight * cos(scalar_product);
|
||||||
|
nbr[i].imag_phi[lambda][k] += weight * sin(scalar_product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect contributions
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
chi += (nbr[i].real_phi[0][k] * nbr[i].real_phi[0][k] + nbr[i].imag_phi[0][k] * nbr[i].imag_phi[0][k] -
|
||||||
|
nbr[i].real_phi[1][k] * nbr[i].real_phi[1][k] - nbr[i].imag_phi[1][k] * nbr[i].imag_phi[1][k]);
|
||||||
|
}
|
||||||
|
chi *= inv_norm_fac;
|
||||||
|
order[i][0] = chi;
|
||||||
|
|
||||||
|
// compute normalized order parameter
|
||||||
|
// and potential energy
|
||||||
|
if (chi > eta) {
|
||||||
|
added_energy += half_u;
|
||||||
|
nbr[i].duchi = 0.0;
|
||||||
|
order[i][1] = sign;
|
||||||
|
} else if (chi < -eta) {
|
||||||
|
added_energy -= half_u;
|
||||||
|
nbr[i].duchi = 0.0;
|
||||||
|
order[i][1] = -sign;
|
||||||
|
} else {
|
||||||
|
omega = omega_pre * chi;
|
||||||
|
sin_om = sin(omega);
|
||||||
|
|
||||||
|
added_energy += half_u * sin_om;
|
||||||
|
nbr[i].duchi = duchi_pre * cos(omega);
|
||||||
|
order[i][1] = sign * sin_om;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute product with potential derivative
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
for (lambda = 0; lambda < 2; ++lambda) {
|
||||||
|
nbr[i].real_phi[lambda][k] *= nbr[i].duchi;
|
||||||
|
nbr[i].imag_phi[lambda][k] *= nbr[i].duchi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set additional local variables
|
||||||
|
double gradient_ii_cos[2][3][3]; // gradient ii cosine term
|
||||||
|
double gradient_ii_sin[2][3][3]; // gradient ii sine term
|
||||||
|
double gradient_ij_vec[2][3][3]; // gradient ij vector term
|
||||||
|
double gradient_ij_sca[2][3]; // gradient ij scalar term
|
||||||
|
tagint idj; // stores id of neighbor j
|
||||||
|
double weight_gradient_prefactor; // gradient prefactor
|
||||||
|
double weight_gradient[3]; // gradient of weight
|
||||||
|
double cos_scalar_product; // cosine of scalar product
|
||||||
|
double sin_scalar_product; // sine of scalar product
|
||||||
|
double gcos_scalar_product; // gradient weight function * cosine of scalar product
|
||||||
|
double gsin_scalar_product; // gradient weight function * sine of scalar product
|
||||||
|
|
||||||
|
// compute force only if synthetic
|
||||||
|
// potential is not zero
|
||||||
|
if (u_0 != 0.0) {
|
||||||
|
// communicate to acquire nbr data for ghost atoms
|
||||||
|
comm->forward_comm_fix(this);
|
||||||
|
|
||||||
|
// loop over owned atoms and compute force
|
||||||
|
// use short neighbor lists
|
||||||
|
for (ii = 0; ii < inum; ++ii) {
|
||||||
|
i = ilist[ii];
|
||||||
|
|
||||||
|
// skip atoms not in group
|
||||||
|
if (!(mask[i] & groupbit)) continue;
|
||||||
|
|
||||||
|
// initializations
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
for (lambda = 0; lambda < 2; ++lambda) {
|
||||||
|
for (dim = 0; dim < 3; ++dim) {
|
||||||
|
gradient_ii_cos[lambda][k][dim] = 0.0;
|
||||||
|
gradient_ii_sin[lambda][k][dim] = 0.0;
|
||||||
|
gradient_ij_vec[lambda][k][dim] = 0.0;
|
||||||
|
}
|
||||||
|
gradient_ij_sca[lambda][k] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n = nbr[i].n;
|
||||||
|
const bool boundary_atom = (nbr[i].duchi != 0.0);
|
||||||
|
|
||||||
|
// loop over all neighbors of atom i
|
||||||
|
for (j = 0; j < n; ++j) {
|
||||||
|
idj = nbr[i].id[j];
|
||||||
|
|
||||||
|
// compute force on atom i if it is close to boundary
|
||||||
|
if ((nbr[idj].duchi != 0.0) || boundary_atom) {
|
||||||
|
delta = &nbr[i].delta[j][0];
|
||||||
|
squared_distance = (delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2]) * inv_squared_cutoff;
|
||||||
|
|
||||||
|
// need weight and its gradient
|
||||||
|
weight = squared_distance * (squared_distance - 2.0) + 1.0;
|
||||||
|
weight_gradient_prefactor = 4.0 * (squared_distance - 1.0) * inv_squared_cutoff;
|
||||||
|
for (dim = 0; dim < 3; ++dim) {
|
||||||
|
weight_gradient[dim] = weight_gradient_prefactor * delta[dim];
|
||||||
|
}
|
||||||
|
|
||||||
|
// (1) compute scalar product and sine and cosine of it
|
||||||
|
// (2) compute product of sine and cosine with gradient of weight function
|
||||||
|
// (3) compute gradient_ii_cos and gradient_ii_sin by summing up result of (2)
|
||||||
|
// (4) compute gradient_ij_vec and gradient_ij_sca
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
for (lambda = 0; lambda < 2; ++lambda) {
|
||||||
|
scalar_product = reciprocal_vectors[lambda][k][0] * delta[0] + reciprocal_vectors[lambda][k][1] * delta[1] + reciprocal_vectors[lambda][k][2] * delta[2];
|
||||||
|
cos_scalar_product = cos(scalar_product);
|
||||||
|
sin_scalar_product = sin(scalar_product);
|
||||||
|
for (dim = 0; dim < 3; ++dim) {
|
||||||
|
gradient_ii_cos[lambda][k][dim] += (gcos_scalar_product = weight_gradient[dim] * cos_scalar_product);
|
||||||
|
gradient_ii_sin[lambda][k][dim] += (gsin_scalar_product = weight_gradient[dim] * sin_scalar_product);
|
||||||
|
gradient_ij_vec[lambda][k][dim] += (nbr[idj].real_phi[lambda][k] * gcos_scalar_product - nbr[idj].imag_phi[lambda][k] * gsin_scalar_product);
|
||||||
|
}
|
||||||
|
gradient_ij_sca[lambda][k] += weight * (nbr[idj].real_phi[lambda][k] * sin_scalar_product + nbr[idj].imag_phi[lambda][k] * cos_scalar_product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sum contributions
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
for (dim = 0; dim < 3; ++dim) {
|
||||||
|
f[i][dim] -= (nbr[i].real_phi[0][k] * gradient_ii_cos[0][k][dim] + nbr[i].imag_phi[0][k] * gradient_ii_sin[0][k][dim] + gradient_ij_vec[0][k][dim] + reciprocal_vectors[1][k][dim] * gradient_ij_sca[1][k]);
|
||||||
|
f[i][dim] += (nbr[i].real_phi[1][k] * gradient_ii_cos[1][k][dim] + nbr[i].imag_phi[1][k] * gradient_ii_sin[1][k][dim] + gradient_ij_vec[1][k][dim] + reciprocal_vectors[0][k][dim] * gradient_ij_sca[0][k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::post_force_respa(int vflag, int ilevel, int iloop) {
|
||||||
|
if (ilevel == ilevel_respa) post_force(vflag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double FixOrientECO::compute_scalar() {
|
||||||
|
double added_energy_total;
|
||||||
|
MPI_Allreduce(&added_energy, &added_energy_total, 1, MPI_DOUBLE, MPI_SUM, world);
|
||||||
|
return added_energy_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int FixOrientECO::pack_forward_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) {
|
||||||
|
int ii, i, jj, j, k, num;
|
||||||
|
tagint id;
|
||||||
|
|
||||||
|
tagint *tag = atom->tag;
|
||||||
|
int nlocal = atom->nlocal;
|
||||||
|
int m = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
k = list[i];
|
||||||
|
num = nbr[k].n;
|
||||||
|
buf[m++] = num;
|
||||||
|
buf[m++] = nbr[k].duchi;
|
||||||
|
|
||||||
|
if (u_0 != 0.0) {
|
||||||
|
for (ii = 0; ii < 2; ++ii) {
|
||||||
|
for (jj = 0; jj < 3; ++jj) {
|
||||||
|
buf[m++] = nbr[i].real_phi[ii][jj];
|
||||||
|
buf[m++] = nbr[i].imag_phi[ii][jj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < num; ++j) {
|
||||||
|
buf[m++] = nbr[k].delta[j][0];
|
||||||
|
buf[m++] = nbr[k].delta[j][1];
|
||||||
|
buf[m++] = nbr[k].delta[j][2];
|
||||||
|
|
||||||
|
// id stored in buf needs to be global ID
|
||||||
|
// if k is a local atom, it stores local IDs, so convert to global
|
||||||
|
// if k is a ghost atom (already comm'd), its IDs are already global
|
||||||
|
|
||||||
|
id = ubuf(nbr[k].id[j]).i;
|
||||||
|
if (k < nlocal) id = ubuf(tag[id]).i;
|
||||||
|
buf[m++] = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::unpack_forward_comm(int n, int first, double *buf) {
|
||||||
|
int ii, i, jj, j, num;
|
||||||
|
int last = first + n;
|
||||||
|
int m = 0;
|
||||||
|
|
||||||
|
for (i = first; i < last; ++i) {
|
||||||
|
nbr[i].n = num = static_cast<int> (buf[m++]);
|
||||||
|
nbr[i].duchi = buf[m++];
|
||||||
|
|
||||||
|
if (u_0 != 0.0) {
|
||||||
|
for (ii = 0; ii < 2; ++ii) {
|
||||||
|
for (jj = 0; jj < 3; ++jj) {
|
||||||
|
nbr[i].real_phi[ii][jj] = buf[m++];
|
||||||
|
nbr[i].imag_phi[ii][jj] = buf[m++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < num; ++j) {
|
||||||
|
nbr[i].delta[j][0] = buf[m++];
|
||||||
|
nbr[i].delta[j][1] = buf[m++];
|
||||||
|
nbr[i].delta[j][2] = buf[m++];
|
||||||
|
nbr[i].id[j] = ubuf(buf[m++]).i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
memory usage of local atom-based arrays
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
double FixOrientECO::memory_usage() {
|
||||||
|
double bytes = nmax * sizeof(Nbr);
|
||||||
|
bytes += 2 * nmax * sizeof(double);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
reciprocal lattice vectors from file input
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::get_reciprocal() {
|
||||||
|
// volume of unit cell A
|
||||||
|
double vol = 0.5 * (dir_vec[0][0] * (dir_vec[1][1] * dir_vec[2][2] - dir_vec[2][1] * dir_vec[1][2]) + dir_vec[1][0] * (dir_vec[2][1] * dir_vec[0][2] - dir_vec[0][1] * dir_vec[2][2]) + dir_vec[2][0] * (dir_vec[0][1] * dir_vec[1][2] - dir_vec[1][1] * dir_vec[0][2])) / MY_PI;
|
||||||
|
double i_vol = 1.0 / vol;
|
||||||
|
|
||||||
|
// grain A: reciprocal_vectors 0
|
||||||
|
reciprocal_vectors[0][0][0] = (dir_vec[1][1] * dir_vec[2][2] - dir_vec[2][1] * dir_vec[1][2]) * i_vol;
|
||||||
|
reciprocal_vectors[0][0][1] = (dir_vec[1][2] * dir_vec[2][0] - dir_vec[2][2] * dir_vec[1][0]) * i_vol;
|
||||||
|
reciprocal_vectors[0][0][2] = (dir_vec[1][0] * dir_vec[2][1] - dir_vec[2][0] * dir_vec[1][1]) * i_vol;
|
||||||
|
|
||||||
|
// grain A: reciprocal_vectors 1
|
||||||
|
reciprocal_vectors[0][1][0] = (dir_vec[2][1] * dir_vec[0][2] - dir_vec[0][1] * dir_vec[2][2]) * i_vol;
|
||||||
|
reciprocal_vectors[0][1][1] = (dir_vec[2][2] * dir_vec[0][0] - dir_vec[0][2] * dir_vec[2][0]) * i_vol;
|
||||||
|
reciprocal_vectors[0][1][2] = (dir_vec[2][0] * dir_vec[0][1] - dir_vec[0][0] * dir_vec[2][1]) * i_vol;
|
||||||
|
|
||||||
|
// grain A: reciprocal_vectors 2
|
||||||
|
reciprocal_vectors[0][2][0] = (dir_vec[0][1] * dir_vec[1][2] - dir_vec[1][1] * dir_vec[0][2]) * i_vol;
|
||||||
|
reciprocal_vectors[0][2][1] = (dir_vec[0][2] * dir_vec[1][0] - dir_vec[1][2] * dir_vec[0][0]) * i_vol;
|
||||||
|
reciprocal_vectors[0][2][2] = (dir_vec[0][0] * dir_vec[1][1] - dir_vec[1][0] * dir_vec[0][1]) * i_vol;
|
||||||
|
|
||||||
|
// volume of unit cell B
|
||||||
|
vol = 0.5 * (dir_vec[3][0] * (dir_vec[4][1] * dir_vec[5][2] - dir_vec[5][1] * dir_vec[4][2]) + dir_vec[4][0] * (dir_vec[5][1] * dir_vec[3][2] - dir_vec[3][1] * dir_vec[5][2]) + dir_vec[5][0] * (dir_vec[3][1] * dir_vec[4][2] - dir_vec[4][1] * dir_vec[3][2])) / MY_PI;
|
||||||
|
i_vol = 1.0 / vol;
|
||||||
|
|
||||||
|
// grain B: reciprocal_vectors 0
|
||||||
|
reciprocal_vectors[1][0][0] = (dir_vec[4][1] * dir_vec[5][2] - dir_vec[5][1] * dir_vec[4][2]) * i_vol;
|
||||||
|
reciprocal_vectors[1][0][1] = (dir_vec[4][2] * dir_vec[5][0] - dir_vec[5][2] * dir_vec[4][0]) * i_vol;
|
||||||
|
reciprocal_vectors[1][0][2] = (dir_vec[4][0] * dir_vec[5][1] - dir_vec[5][0] * dir_vec[4][1]) * i_vol;
|
||||||
|
|
||||||
|
// grain B: reciprocal_vectors 1
|
||||||
|
reciprocal_vectors[1][1][0] = (dir_vec[5][1] * dir_vec[3][2] - dir_vec[3][1] * dir_vec[5][2]) * i_vol;
|
||||||
|
reciprocal_vectors[1][1][1] = (dir_vec[5][2] * dir_vec[3][0] - dir_vec[3][2] * dir_vec[5][0]) * i_vol;
|
||||||
|
reciprocal_vectors[1][1][2] = (dir_vec[5][0] * dir_vec[3][1] - dir_vec[3][0] * dir_vec[5][1]) * i_vol;
|
||||||
|
|
||||||
|
// grain B: reciprocal_vectors 2
|
||||||
|
reciprocal_vectors[1][2][0] = (dir_vec[3][1] * dir_vec[4][2] - dir_vec[4][1] * dir_vec[3][2]) * i_vol;
|
||||||
|
reciprocal_vectors[1][2][1] = (dir_vec[3][2] * dir_vec[4][0] - dir_vec[4][2] * dir_vec[3][0]) * i_vol;
|
||||||
|
reciprocal_vectors[1][2][2] = (dir_vec[3][0] * dir_vec[4][1] - dir_vec[4][0] * dir_vec[3][1]) * i_vol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
normalization factor
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void FixOrientECO::get_norm(int &neigh) {
|
||||||
|
// set up local variables
|
||||||
|
double delta[3]; // relative position
|
||||||
|
double squared_distance; // squared distance of atoms i and j
|
||||||
|
double weight; // weight function for atoms i and j
|
||||||
|
double wsum = 0.0; // sum of all weight functions
|
||||||
|
double scalar_product; // scalar product
|
||||||
|
double reesum[3] = {0.0, 0.0, 0.0}; // sum of real part
|
||||||
|
double imesum[3] = {0.0, 0.0, 0.0}; // sum of imaginary part
|
||||||
|
|
||||||
|
int max_co = 4; // will produce wrong results for rcut > 3 * lattice constant
|
||||||
|
|
||||||
|
neigh = 0; // count number of neighbors used
|
||||||
|
|
||||||
|
// loop over ideal lattice positions
|
||||||
|
int i, k, idx[3];
|
||||||
|
for (idx[0] = -max_co; idx[0] <= max_co; ++idx[0]) {
|
||||||
|
for (idx[1] = -max_co; idx[1] <= max_co; ++idx[1]) {
|
||||||
|
for (idx[2] = -max_co; idx[2] <= max_co; ++idx[2]) {
|
||||||
|
// distance of atoms
|
||||||
|
for (i = 0; i < 3; ++i) {
|
||||||
|
delta[i] = dir_vec[0][i] * idx[0] + dir_vec[1][i] * idx[1] + dir_vec[2][i] * idx[2];
|
||||||
|
}
|
||||||
|
squared_distance = delta[0] * delta[0] + delta[1] * delta[1] + delta[2] * delta[2];
|
||||||
|
|
||||||
|
// check if atom is within cutoff region
|
||||||
|
if ((squared_distance != 0.0) and (squared_distance < squared_cutoff)) {
|
||||||
|
++neigh;
|
||||||
|
squared_distance *= inv_squared_cutoff;
|
||||||
|
|
||||||
|
// weight
|
||||||
|
weight = squared_distance * (squared_distance - 2.0) + 1.0;
|
||||||
|
wsum += weight;
|
||||||
|
|
||||||
|
// three reciprocal directions
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
scalar_product = reciprocal_vectors[1][k][0] * delta[0] + reciprocal_vectors[1][k][1] * delta[1] + reciprocal_vectors[1][k][2] * delta[2];
|
||||||
|
reesum[k] += weight * cos(scalar_product);
|
||||||
|
imesum[k] -= weight * sin(scalar_product);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute normalization
|
||||||
|
norm_fac = 3.0 * wsum * wsum;
|
||||||
|
for (k = 0; k < 3; ++k) {
|
||||||
|
norm_fac -= reesum[k] * reesum[k] + imesum[k] * imesum[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
29
src/MISC/fix_eco_force.h → src/USER-MISC/fix_orient_eco.h
Normal file → Executable file
29
src/MISC/fix_eco_force.h → src/USER-MISC/fix_orient_eco.h
Normal file → Executable file
@ -13,34 +13,21 @@
|
|||||||
|
|
||||||
#ifdef FIX_CLASS
|
#ifdef FIX_CLASS
|
||||||
|
|
||||||
FixStyle(eco/force,FixECOForce)
|
FixStyle(orient/eco,FixOrientECO)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifndef LMP_FIX_ECO_FORCE_H
|
#ifndef LMP_FIX_ORIENT_ECO_H
|
||||||
#define LMP_FIX_ECO_FORCE_H
|
#define LMP_FIX_ORIENT_ECO_H
|
||||||
|
|
||||||
#include "fix.h"
|
#include "fix.h"
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
#define FIX_ECO_FORCE_MAX_NEIGHBORS 24
|
class FixOrientECO : public Fix {
|
||||||
|
|
||||||
class FixECOForce : public Fix {
|
|
||||||
public:
|
public:
|
||||||
struct Nbr {
|
FixOrientECO(class LAMMPS *, int, char **);
|
||||||
int n; // # of neighbors
|
~FixOrientECO();
|
||||||
tagint id[FIX_ECO_FORCE_MAX_NEIGHBORS]; // IDs of each neighbor
|
|
||||||
// if center atom is owned, these are local IDs
|
|
||||||
// if center atom is ghost, these are global IDs
|
|
||||||
double duchi; // potential derivative
|
|
||||||
double delta[FIX_ECO_FORCE_MAX_NEIGHBORS][3]; // difference vectors
|
|
||||||
double real_phi[2][3]; // real part of wave function
|
|
||||||
double imag_phi[2][3]; // imaginary part of wave function
|
|
||||||
};
|
|
||||||
|
|
||||||
FixECOForce(class LAMMPS *, int, char **);
|
|
||||||
~FixECOForce();
|
|
||||||
int setmask();
|
int setmask();
|
||||||
void init();
|
void init();
|
||||||
void init_list(int, class NeighList *);
|
void init_list(int, class NeighList *);
|
||||||
@ -53,6 +40,8 @@ class FixECOForce : public Fix {
|
|||||||
double memory_usage();
|
double memory_usage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Nbr; // private struct for managing precomputed terms
|
||||||
|
|
||||||
int me; // this processors rank
|
int me; // this processors rank
|
||||||
int nmax; // maximal # of owned + ghost atoms on this processor
|
int nmax; // maximal # of owned + ghost atoms on this processor
|
||||||
int ilevel_respa; // used for RESPA integrator only
|
int ilevel_respa; // used for RESPA integrator only
|
||||||
@ -86,6 +75,6 @@ class FixECOForce : public Fix {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // LMP_FIX_ECO_FORCE_H
|
#endif // LMP_FIX_ORIENT_ECO_H
|
||||||
#endif // FIX_CLASS
|
#endif // FIX_CLASS
|
||||||
|
|
||||||
123
src/MISC/fix_eco_force.cpp → src/fix_orient_eco.cpp
Normal file → Executable file
123
src/MISC/fix_eco_force.cpp → src/fix_orient_eco.cpp
Normal file → Executable file
@ -15,33 +15,30 @@
|
|||||||
Contributing authors: Adrian A. Schratt and Volker Mohles (ICAMS)
|
Contributing authors: Adrian A. Schratt and Volker Mohles (ICAMS)
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
#include "math.h"
|
#include "fix_orient_eco.h"
|
||||||
#include "string.h"
|
#include <mpi.h>
|
||||||
#include "stdlib.h"
|
#include <cmath>
|
||||||
#include "mpi.h"
|
#include <cstring>
|
||||||
#include "fix_eco_force.h"
|
|
||||||
#include "atom.h"
|
#include "atom.h"
|
||||||
#include "update.h"
|
|
||||||
#include "domain.h"
|
|
||||||
#include "respa.h"
|
|
||||||
#include "force.h"
|
|
||||||
#include "pair.h"
|
|
||||||
#include "neighbor.h"
|
|
||||||
#include "neigh_list.h"
|
|
||||||
#include "neigh_request.h"
|
|
||||||
#include "citeme.h"
|
#include "citeme.h"
|
||||||
#include "comm.h"
|
#include "comm.h"
|
||||||
#include "output.h"
|
#include "error.h"
|
||||||
|
#include "force.h"
|
||||||
#include "math_const.h"
|
#include "math_const.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "error.h"
|
#include "neigh_list.h"
|
||||||
|
#include "neigh_request.h"
|
||||||
|
#include "neighbor.h"
|
||||||
|
#include "pair.h"
|
||||||
|
#include "respa.h"
|
||||||
|
#include "update.h"
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
using namespace FixConst;
|
using namespace FixConst;
|
||||||
using namespace MathConst;
|
using namespace MathConst;
|
||||||
|
|
||||||
static const char cite_fix_eco_force[] =
|
static const char cite_fix_orient_eco[] =
|
||||||
"fix eco/force command:\n\n"
|
"fix orient/eco command:\n\n"
|
||||||
"@Article{Schratt20,\n"
|
"@Article{Schratt20,\n"
|
||||||
" author = {A. A. Schratt, V. Mohles},\n"
|
" author = {A. A. Schratt, V. Mohles},\n"
|
||||||
" title = {Efficient calculation of the ECO driving force for atomistic simulations of grain boundary motion},\n"
|
" title = {Efficient calculation of the ECO driving force for atomistic simulations of grain boundary motion},\n"
|
||||||
@ -53,19 +50,33 @@ static const char cite_fix_eco_force[] =
|
|||||||
" url = {https://doi.org/10.1016/j.commatsci.2020.109774}\n"
|
" url = {https://doi.org/10.1016/j.commatsci.2020.109774}\n"
|
||||||
"}\n\n";
|
"}\n\n";
|
||||||
|
|
||||||
|
#define FIX_ORIENT_ECO_MAX_NEIGH 24
|
||||||
|
|
||||||
|
struct FixOrientECO::Nbr {
|
||||||
|
public:
|
||||||
|
int n; // # of neighbors
|
||||||
|
tagint id[FIX_ORIENT_ECO_MAX_NEIGH]; // IDs of each neighbor
|
||||||
|
// if center atom is owned, these are local IDs
|
||||||
|
// if center atom is ghost, these are global IDs
|
||||||
|
double duchi; // potential derivative
|
||||||
|
double delta[FIX_ORIENT_ECO_MAX_NEIGH][3]; // difference vectors
|
||||||
|
double real_phi[2][3]; // real part of wave function
|
||||||
|
double imag_phi[2][3]; // imaginary part of wave function
|
||||||
|
};
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
FixECOForce::FixECOForce(LAMMPS *lmp, int narg, char **arg) :
|
FixOrientECO::FixOrientECO(LAMMPS *lmp, int narg, char **arg) :
|
||||||
Fix(lmp, narg, arg),
|
Fix(lmp, narg, arg),
|
||||||
dir_filename(NULL), order(NULL), nbr(NULL), list(NULL)
|
dir_filename(NULL), order(NULL), nbr(NULL), list(NULL)
|
||||||
{
|
{
|
||||||
if (lmp->citeme) lmp->citeme->add(cite_fix_eco_force);
|
if (lmp->citeme) lmp->citeme->add(cite_fix_orient_eco);
|
||||||
|
|
||||||
// get rank of this processor
|
// get rank of this processor
|
||||||
MPI_Comm_rank(world, &me);
|
MPI_Comm_rank(world, &me);
|
||||||
|
|
||||||
// check for illegal command
|
// check for illegal command
|
||||||
if (narg != 7) error->all(FLERR, "Illegal fix eco/force command");
|
if (narg != 7) error->all(FLERR, "Illegal fix orient/eco command");
|
||||||
|
|
||||||
// set fix flags
|
// set fix flags
|
||||||
scalar_flag = 1; // computes scalar
|
scalar_flag = 1; // computes scalar
|
||||||
@ -76,10 +87,10 @@ FixECOForce::FixECOForce(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
peratom_freq = 1; //
|
peratom_freq = 1; //
|
||||||
|
|
||||||
// parse input parameters
|
// parse input parameters
|
||||||
u_0 = atof(arg[3]);
|
u_0 = force->numeric(FLERR, arg[3]);
|
||||||
sign = (u_0 >= 0.0 ? 1 : -1);
|
sign = (u_0 >= 0.0 ? 1 : -1);
|
||||||
eta = atof(arg[4]);
|
eta = force->numeric(FLERR, arg[4]);
|
||||||
r_cut = atof(arg[5]);
|
r_cut = force->numeric(FLERR, arg[5]);
|
||||||
|
|
||||||
// read reference orientations from file
|
// read reference orientations from file
|
||||||
// work on rank 0 only
|
// work on rank 0 only
|
||||||
@ -91,13 +102,13 @@ FixECOForce::FixECOForce(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
char *result;
|
char *result;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
FILE *infile = fopen(dir_filename, "r");
|
FILE *infile = force->open_potential(dir_filename);
|
||||||
if (infile == NULL) error->one(FLERR, "Fix eco/force file open failed");
|
if (infile == NULL) error->one(FLERR, "Fix orient/eco file open failed");
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
result = fgets(line, IMGMAX, infile);
|
result = fgets(line, IMGMAX, infile);
|
||||||
if (!result) error->one(FLERR, "Fix eco/force file read failed");
|
if (!result) error->one(FLERR, "Fix orient/eco file read failed");
|
||||||
count = sscanf(line, "%lg %lg %lg", &dir_vec[i][0], &dir_vec[i][1], &dir_vec[i][2]);
|
count = sscanf(line, "%lg %lg %lg", &dir_vec[i][0], &dir_vec[i][1], &dir_vec[i][2]);
|
||||||
if (count != 3) error->one(FLERR, "Fix eco/force file read failed");
|
if (count != 3) error->one(FLERR, "Fix orient/eco file read failed");
|
||||||
}
|
}
|
||||||
fclose(infile);
|
fclose(infile);
|
||||||
|
|
||||||
@ -119,14 +130,14 @@ FixECOForce::FixECOForce(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
MPI_Bcast(&inv_eta, 1, MPI_DOUBLE, 0, world); // communicate inverse threshold
|
MPI_Bcast(&inv_eta, 1, MPI_DOUBLE, 0, world); // communicate inverse threshold
|
||||||
|
|
||||||
// set comm size needed by this Fix
|
// set comm size needed by this Fix
|
||||||
if (u_0 != 0.0) comm_forward = 110;
|
if (u_0 != 0.0) comm_forward = 14 + 4 * FIX_ORIENT_ECO_MAX_NEIGH; // needed for communication of full Nbr struct
|
||||||
else comm_forward = 98;
|
else comm_forward = 2 + 4 * FIX_ORIENT_ECO_MAX_NEIGH; // real_phi and imag_phi not needed for communication
|
||||||
|
|
||||||
added_energy = 0.0; // initial energy
|
added_energy = 0.0; // initial energy
|
||||||
|
|
||||||
nmax = atom->nmax;
|
nmax = atom->nmax;
|
||||||
nbr = (Nbr *) memory->smalloc(nmax * sizeof(Nbr), "eco/force:nbr");
|
nbr = (Nbr *) memory->smalloc(nmax * sizeof(Nbr), "orient/eco:nbr");
|
||||||
memory->create(order, nmax, 2, "eco/force:order");
|
memory->create(order, nmax, 2, "orient/eco:order");
|
||||||
array_atom = order;
|
array_atom = order;
|
||||||
|
|
||||||
// zero the array since a variable may access it before first run
|
// zero the array since a variable may access it before first run
|
||||||
@ -135,7 +146,7 @@ FixECOForce::FixECOForce(LAMMPS *lmp, int narg, char **arg) :
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
FixECOForce::~FixECOForce() {
|
FixOrientECO::~FixOrientECO() {
|
||||||
memory->destroy(order);
|
memory->destroy(order);
|
||||||
memory->sfree(nbr);
|
memory->sfree(nbr);
|
||||||
delete[] dir_filename;
|
delete[] dir_filename;
|
||||||
@ -143,7 +154,7 @@ FixECOForce::~FixECOForce() {
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
int FixECOForce::setmask() {
|
int FixOrientECO::setmask() {
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
mask |= POST_FORCE;
|
mask |= POST_FORCE;
|
||||||
mask |= THERMO_ENERGY;
|
mask |= THERMO_ENERGY;
|
||||||
@ -153,7 +164,7 @@ int FixECOForce::setmask() {
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::init() {
|
void FixOrientECO::init() {
|
||||||
// get this processors rank
|
// get this processors rank
|
||||||
MPI_Comm_rank(world, &me);
|
MPI_Comm_rank(world, &me);
|
||||||
|
|
||||||
@ -161,14 +172,19 @@ void FixECOForce::init() {
|
|||||||
if (me == 0) {
|
if (me == 0) {
|
||||||
int neigh;
|
int neigh;
|
||||||
get_norm(neigh);
|
get_norm(neigh);
|
||||||
printf("fix eco/force: cutoff=%f norm_fac=%f neighbors=%i\n", r_cut, norm_fac, neigh);
|
if (screen) {
|
||||||
|
fprintf(screen, " fix orient/eco: cutoff=%f norm_fac=%f neighbors=%i\n", r_cut, norm_fac, neigh);
|
||||||
|
}
|
||||||
|
if (logfile) {
|
||||||
|
fprintf(logfile, " fix orient/eco: cutoff=%f norm_fac=%f neighbors=%i\n", r_cut, norm_fac, neigh);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inv_norm_fac = 1.0 / norm_fac;
|
inv_norm_fac = 1.0 / norm_fac;
|
||||||
|
|
||||||
// check parameters
|
// check parameters
|
||||||
if (r_cut > force->pair->cutforce) {
|
if (r_cut > force->pair->cutforce) {
|
||||||
error->all(FLERR, "Pair cutoff too small: use 'hybrid/overlay' to set the pair cutoff larger than the fix eco/force cutoff");
|
error->all(FLERR, "Cutoff radius used by fix orient/eco must be smaller than force cutoff");
|
||||||
}
|
}
|
||||||
|
|
||||||
// communicate normalization factor
|
// communicate normalization factor
|
||||||
@ -188,18 +204,17 @@ void FixECOForce::init() {
|
|||||||
neighbor->requests[irequest]->fix = 1;
|
neighbor->requests[irequest]->fix = 1;
|
||||||
neighbor->requests[irequest]->half = 0;
|
neighbor->requests[irequest]->half = 0;
|
||||||
neighbor->requests[irequest]->full = 1;
|
neighbor->requests[irequest]->full = 1;
|
||||||
neighbor->requests[irequest]->ghost = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::init_list(int id, NeighList *ptr) {
|
void FixOrientECO::init_list(int id, NeighList *ptr) {
|
||||||
list = ptr;
|
list = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::setup(int vflag) {
|
void FixOrientECO::setup(int vflag) {
|
||||||
if (strstr(update->integrate_style, "verlet"))
|
if (strstr(update->integrate_style, "verlet"))
|
||||||
post_force(vflag);
|
post_force(vflag);
|
||||||
else {
|
else {
|
||||||
@ -211,7 +226,7 @@ void FixECOForce::setup(int vflag) {
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::post_force(int vflag) {
|
void FixOrientECO::post_force(int vflag) {
|
||||||
// set local variables
|
// set local variables
|
||||||
int ii, i, jj, j; // loop variables and atom IDs
|
int ii, i, jj, j; // loop variables and atom IDs
|
||||||
int k; // variable to loop over 3 reciprocal directions
|
int k; // variable to loop over 3 reciprocal directions
|
||||||
@ -250,8 +265,8 @@ void FixECOForce::post_force(int vflag) {
|
|||||||
nmax = nall;
|
nmax = nall;
|
||||||
memory->destroy(nbr);
|
memory->destroy(nbr);
|
||||||
memory->destroy(order);
|
memory->destroy(order);
|
||||||
nbr = (Nbr *) memory->smalloc(nmax * sizeof(Nbr), "eco/force:nbr");
|
nbr = (Nbr *) memory->smalloc(nmax * sizeof(Nbr), "orient/eco:nbr");
|
||||||
memory->create(order, nmax, 2, "eco/force:order");
|
memory->create(order, nmax, 2, "orient/eco:order");
|
||||||
array_atom = order;
|
array_atom = order;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,8 +291,8 @@ void FixECOForce::post_force(int vflag) {
|
|||||||
squared_distance = dx * dx + dy * dy + dz * dz;
|
squared_distance = dx * dx + dy * dy + dz * dz;
|
||||||
|
|
||||||
if (squared_distance < squared_cutoff) {
|
if (squared_distance < squared_cutoff) {
|
||||||
if (n >= FIX_ECO_FORCE_MAX_NEIGHBORS) {
|
if (n >= FIX_ORIENT_ECO_MAX_NEIGH) {
|
||||||
error->one(FLERR, "Fix eco/force maximal number of neighbors exceeded");
|
error->one(FLERR, "Fix orient/eco maximal number of neighbors exceeded");
|
||||||
}
|
}
|
||||||
nbr[i].id[n] = static_cast<tagint> (j);
|
nbr[i].id[n] = static_cast<tagint> (j);
|
||||||
nbr[i].delta[n][0] = dx;
|
nbr[i].delta[n][0] = dx;
|
||||||
@ -444,13 +459,13 @@ void FixECOForce::post_force(int vflag) {
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::post_force_respa(int vflag, int ilevel, int iloop) {
|
void FixOrientECO::post_force_respa(int vflag, int ilevel, int iloop) {
|
||||||
if (ilevel == ilevel_respa) post_force(vflag);
|
if (ilevel == ilevel_respa) post_force(vflag);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
double FixECOForce::compute_scalar() {
|
double FixOrientECO::compute_scalar() {
|
||||||
double added_energy_total;
|
double added_energy_total;
|
||||||
MPI_Allreduce(&added_energy, &added_energy_total, 1, MPI_DOUBLE, MPI_SUM, world);
|
MPI_Allreduce(&added_energy, &added_energy_total, 1, MPI_DOUBLE, MPI_SUM, world);
|
||||||
return added_energy_total;
|
return added_energy_total;
|
||||||
@ -458,7 +473,7 @@ double FixECOForce::compute_scalar() {
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
int FixECOForce::pack_forward_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) {
|
int FixOrientECO::pack_forward_comm(int n, int *list, double *buf, int pbc_flag, int *pbc) {
|
||||||
int ii, i, jj, j, k, num;
|
int ii, i, jj, j, k, num;
|
||||||
tagint id;
|
tagint id;
|
||||||
|
|
||||||
@ -490,8 +505,8 @@ int FixECOForce::pack_forward_comm(int n, int *list, double *buf, int pbc_flag,
|
|||||||
// if k is a local atom, it stores local IDs, so convert to global
|
// if k is a local atom, it stores local IDs, so convert to global
|
||||||
// if k is a ghost atom (already comm'd), its IDs are already global
|
// if k is a ghost atom (already comm'd), its IDs are already global
|
||||||
|
|
||||||
id = nbr[k].id[j];
|
id = ubuf(nbr[k].id[j]).i;
|
||||||
if (k < nlocal) id = tag[id];
|
if (k < nlocal) id = ubuf(tag[id]).i;
|
||||||
buf[m++] = id;
|
buf[m++] = id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -501,7 +516,7 @@ int FixECOForce::pack_forward_comm(int n, int *list, double *buf, int pbc_flag,
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::unpack_forward_comm(int n, int first, double *buf) {
|
void FixOrientECO::unpack_forward_comm(int n, int first, double *buf) {
|
||||||
int ii, i, jj, j, num;
|
int ii, i, jj, j, num;
|
||||||
int last = first + n;
|
int last = first + n;
|
||||||
int m = 0;
|
int m = 0;
|
||||||
@ -523,7 +538,7 @@ void FixECOForce::unpack_forward_comm(int n, int first, double *buf) {
|
|||||||
nbr[i].delta[j][0] = buf[m++];
|
nbr[i].delta[j][0] = buf[m++];
|
||||||
nbr[i].delta[j][1] = buf[m++];
|
nbr[i].delta[j][1] = buf[m++];
|
||||||
nbr[i].delta[j][2] = buf[m++];
|
nbr[i].delta[j][2] = buf[m++];
|
||||||
nbr[i].id[j] = static_cast<tagint> (buf[m++]);
|
nbr[i].id[j] = ubuf(buf[m++]).i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -532,7 +547,7 @@ void FixECOForce::unpack_forward_comm(int n, int first, double *buf) {
|
|||||||
memory usage of local atom-based arrays
|
memory usage of local atom-based arrays
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
double FixECOForce::memory_usage() {
|
double FixOrientECO::memory_usage() {
|
||||||
double bytes = nmax * sizeof(Nbr);
|
double bytes = nmax * sizeof(Nbr);
|
||||||
bytes += 2 * nmax * sizeof(double);
|
bytes += 2 * nmax * sizeof(double);
|
||||||
return bytes;
|
return bytes;
|
||||||
@ -542,7 +557,7 @@ double FixECOForce::memory_usage() {
|
|||||||
reciprocal lattice vectors from file input
|
reciprocal lattice vectors from file input
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::get_reciprocal() {
|
void FixOrientECO::get_reciprocal() {
|
||||||
// volume of unit cell A
|
// volume of unit cell A
|
||||||
double vol = 0.5 * (dir_vec[0][0] * (dir_vec[1][1] * dir_vec[2][2] - dir_vec[2][1] * dir_vec[1][2]) + dir_vec[1][0] * (dir_vec[2][1] * dir_vec[0][2] - dir_vec[0][1] * dir_vec[2][2]) + dir_vec[2][0] * (dir_vec[0][1] * dir_vec[1][2] - dir_vec[1][1] * dir_vec[0][2])) / MY_PI;
|
double vol = 0.5 * (dir_vec[0][0] * (dir_vec[1][1] * dir_vec[2][2] - dir_vec[2][1] * dir_vec[1][2]) + dir_vec[1][0] * (dir_vec[2][1] * dir_vec[0][2] - dir_vec[0][1] * dir_vec[2][2]) + dir_vec[2][0] * (dir_vec[0][1] * dir_vec[1][2] - dir_vec[1][1] * dir_vec[0][2])) / MY_PI;
|
||||||
double i_vol = 1.0 / vol;
|
double i_vol = 1.0 / vol;
|
||||||
@ -586,7 +601,7 @@ void FixECOForce::get_reciprocal() {
|
|||||||
normalization factor
|
normalization factor
|
||||||
------------------------------------------------------------------------- */
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
void FixECOForce::get_norm(int &neigh) {
|
void FixOrientECO::get_norm(int &neigh) {
|
||||||
// set up local variables
|
// set up local variables
|
||||||
double delta[3]; // relative position
|
double delta[3]; // relative position
|
||||||
double squared_distance; // squared distance of atoms i and j
|
double squared_distance; // squared distance of atoms i and j
|
||||||
80
src/fix_orient_eco.h
Executable file
80
src/fix_orient_eco.h
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||||
|
http://lammps.sandia.gov, Sandia National Laboratories
|
||||||
|
Steve Plimpton, sjplimp@sandia.gov
|
||||||
|
|
||||||
|
Copyright (2003) Sandia Corporation. Under the terms of Contract
|
||||||
|
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
|
||||||
|
certain rights in this software. This software is distributed under
|
||||||
|
the GNU General Public License.
|
||||||
|
|
||||||
|
See the README file in the top-level LAMMPS directory.
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#ifdef FIX_CLASS
|
||||||
|
|
||||||
|
FixStyle(orient/eco,FixOrientECO)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef LMP_FIX_ORIENT_ECO_H
|
||||||
|
#define LMP_FIX_ORIENT_ECO_H
|
||||||
|
|
||||||
|
#include "fix.h"
|
||||||
|
|
||||||
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class FixOrientECO : public Fix {
|
||||||
|
public:
|
||||||
|
FixOrientECO(class LAMMPS *, int, char **);
|
||||||
|
~FixOrientECO();
|
||||||
|
int setmask();
|
||||||
|
void init();
|
||||||
|
void init_list(int, class NeighList *);
|
||||||
|
void setup(int);
|
||||||
|
void post_force(int);
|
||||||
|
void post_force_respa(int, int, int);
|
||||||
|
double compute_scalar();
|
||||||
|
int pack_forward_comm(int, int *, double *, int, int *);
|
||||||
|
void unpack_forward_comm(int, int, double *);
|
||||||
|
double memory_usage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Nbr; // private struct for managing precomputed terms
|
||||||
|
|
||||||
|
int me; // this processors rank
|
||||||
|
int nmax; // maximal # of owned + ghost atoms on this processor
|
||||||
|
int ilevel_respa; // used for RESPA integrator only
|
||||||
|
|
||||||
|
int sign; // from sign of u
|
||||||
|
double u_0; // synthetic potential energy
|
||||||
|
double half_u; // half synthetic potential energy
|
||||||
|
double eta; // threshold for thermal effects
|
||||||
|
double inv_eta; // inverse threshold for thermal effects
|
||||||
|
double r_cut; // cutoff radius
|
||||||
|
double squared_cutoff; // squared cutoff radius
|
||||||
|
double inv_squared_cutoff; // inverse squared cutoff radius
|
||||||
|
char *dir_filename; // filename of reference grain input
|
||||||
|
double dir_vec[6][3]; // direct lattice vectors
|
||||||
|
double reciprocal_vectors[2][3][3]; // reciprocal lattice vectors
|
||||||
|
|
||||||
|
double added_energy; // energy added by fix
|
||||||
|
|
||||||
|
double **order; // order parameter and normalized order
|
||||||
|
// parameter per atom
|
||||||
|
|
||||||
|
double norm_fac; // normalization constant
|
||||||
|
double inv_norm_fac; // inverse normalization constant
|
||||||
|
|
||||||
|
Nbr *nbr; // pointer on array of Nbr structs
|
||||||
|
class NeighList *list; // LAMMPS' neighbor list
|
||||||
|
|
||||||
|
void get_reciprocal(); // calculate reciprocal lattice vectors
|
||||||
|
void get_norm(int &); // compute normalization factor
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LMP_FIX_ORIENT_ECO_H
|
||||||
|
#endif // FIX_CLASS
|
||||||
|
|
||||||
Reference in New Issue
Block a user